2015-11-07 76 views
0

我正在使用C++ 11一个工厂模式,其是在我的主()函数的范围和被调用这样的:C++寿命返回智能指针

histogram_requests -> AddNewPostfix(Postfix_factory :: get_postfix("Layers", ntuple_reader)); 

Postfix_factory :: get_postfix()是一个静态成员函数,返回std :: unique_ptr <后缀>。一个示例返回值是:

return std :: move(std :: unique_ptr<Postfix>(new Layers_postfix(ntuple_reader_p))); 

我的第一个问题是,如果这实际上是有效的吗?返回的指针是否在main()范围的末尾被销毁?

第二件事是我想把这个指针传递给一个函数。什么是正确的做法?我的程序编译当我设置AddNewPostFix()到任何一个的std ::的unique_ptr的自变量类型或的std ::的unique_ptr & &但未能作为一个简单的参考。我不想让我的AddNewPostFix()意外删除我的指针中的数据,但我不确定这些是否安全。任何人都可以告诉我如何正确和安全地做到这一点?

回答

-1

返回智能指针是好的,直到您决定需要将其保存在不同类型的智能指针中。我只是返回一个原始指针,让调用者决定它想要做什么。在你的情况下,std :: move是不必要的。

要将它传递给函数,请将函数参数设置为const T &,并在智能指针上使用解引用运算符。

void someFunction(const T& t) 
{ 
} 

std::unique_ptr<T> t = ...; 
SomeFunction(*t); 
+0

我其实有点困惑。如果没有** std :: move()**,我的唯一指针中的数据不会被删除(因为函数返回后让unique_ptr的实例超出范围) –

+0

@AdamHunyadi:是的,它会被删除。这就是它的重点。但到了这个时候,'someFunction'已经完成了它的工作,所以没有问题,除非'someFunction'决定在其他地方存储一个指向'T'的指针,这将是非常邪恶的('global_pointer =&t' )。 –

1
return std :: move(std :: unique_ptr<Postfix>(new Layers_postfix(ntuple_reader_p))); 

有两件事值得关注的位置:

  1. You don't need std::move in your return statement.

  2. 您应该使用std::make_unique。它仅在C++ 14以后才正式支持,但无论是您的编译器都支持它,还是您可以轻松创建它自己的版本。

是在我main()范围最终摧毁了返回的指针?

“返回的指针”可以指几件事情。

std::unique_ptr物体当然被破坏。当范围结束时,所有本地对象都被销毁。 std::unique_ptr内的原始指针数据成员也被破坏,但这很简单。

我想你的真正意思是指向的对象,它由std::unique_ptr管理,即动态分配的Postfix。该对象也将被销毁,是的,因为当您的main结束时,std::unique_ptr不会移动到任何位置。

如果Postfix不会被破坏,那么你会有内存泄漏,std::unique_ptr几乎没用,不是吗?

第二件事是我想将这个指针传递给一个函数。什么是正确的做法?

这个问题太宽泛了。 Herb Sutter曾写过an entire article about passing smart pointers to functions。这是一篇很长的文章,也有很多有趣的用户评论。你一定要读它。这里是萨特的准则:


,除非你想 使用不通过智能指针作为函数参数或操纵智能指针本身,如共享或 所有权转让。


,*或&,而不是由智能指针由值不想传递对象。


使用按值 unique_ptr参数

Express中的“下沉”功能。


只使用一个非const unique_ptr&参数修改unique_ptr


不要使用const unique_ptr&作为参数;使用widget*代替


快车函数将存储和使用由值shared_ptr参数共享堆对象的所有权。


只使用一个非const shared_ptr&参数修改shared_ptr。只有当您不确定是否需要复制和共享所有权时,才使用const shared_ptr&作为参数;否则使用widget*代替(或者如果不可以,则使用widget&)。


我不想让我的AddNewPostFix()在我的指针意外删除的数据,但我不知道,要么这些是安全的。

最安全的事情不会通过指针,而是通过一个Postfix&Postfix const&。当然,人们仍然可以尝试delete &postfix或采用类似的不良做法。但俗话说,C++防止墨菲,而不是反对马基雅维利。

下面是一个完整的例子:

#include <memory> 
#include <string> 
#include <iostream> 

struct Postfix 
{ 
    std::string layers; 
    int ntuple_reader; 

    Postfix(std::string const& layers, int ntuple_reader) : 
     layers(layers), 
     ntuple_reader(ntuple_reader) 
    { 
    } 

    ~Postfix() 
    { 
     std::cout << "dtr\n"; 
    } 
}; 

std::unique_ptr<Postfix> get_postfix(std::string const& layers, int ntuple_reader) 
{ 
    return std::make_unique<Postfix>(layers, ntuple_reader); 
} 

void AddNewPostfix(Postfix const& postfix) 
{ 
    std::cout << "AddNewPostfix\n"; 
    // do something with postfix.layers and postfix.ntuple_reader 
} 

int main() 
{ 
    int ntuple_reader = 123; 
    auto postfix_ptr = get_postfix("Layers", ntuple_reader); 
    AddNewPostfix(*postfix_ptr); 
} 

正如你在输出看到的,Postfix析构函数正确调用在main末。

+0

** 0。 )**我没有C++ 14的支持,所以我买不起** make_unique()** ** 1。 )**我真的不明白为什么我不应该移动unique_ptr。不应该在我的工厂函数结束时将其删除(并将其转换为右值)? ** 2。 )**关于主要问题(我的unique_ptr的生命周期),我真的很好奇它是否一直存在直到主结束(不是如果它在那里被删除),但是从你的回答中我推断它是物理存在的在我的**主()**,所以**你已经回答了我的问题。** ** 3。 )** **谢谢你的例子!** –

+0

@AdamHunyadi:0)'make_unique'很容易编写你自己。 1)对于具有移动构造函数的类,返回意味着移动。 2)不确定你的意思......'main'与其他函数没有什么不同。 3)欢迎您:) –

+0

您给了我一个好主意,在调用析构函数时编写调试提示符。不幸的是我的析构函数在我的AddNewPostfix()调用后立即调用。这是不正确的。 –