我在C ++ 11中使用工厂模式,它在我的 main()函数的范围内,并且被调用如下:
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&amp;&amp; 时,我的程序会编译但作为一个简单的参考失败。我不想让我的 AddNewPostFix()意外删除指针中的数据,但我不确定其中任何一个都是安全的。谁能告诉我如何正确安全地做到这一点?
答案 0 :(得分:1)
return std :: move( std :: unique_ptr<Postfix>( new Layers_postfix( ntuple_reader_p ) ));
这里有两点值得注意:
您应该使用std::make_unique
。它仅在C ++ 14之后得到官方支持,但无论如何您的编译器都支持它,或者您可以轻松创建自己的版本。
返回的指针是否在
main()
范围的末尾被销毁?
“返回的指针”可以引用几件事。
当然,std::unique_ptr
对象已被销毁。当范围结束时,所有本地对象都将被销毁。 std::unique_ptr
内部的原始指针数据成员也被销毁,但这很简单。
我认为你真正的意思是指向的对象,由std::unique_ptr
管理,即动态分配的Postfix
。该对象也将被销毁,是的,因为当std::unique_ptr
结束时,main
不会移动到任何位置。
如果Postfix
不会被破坏,那么你就会有内存泄漏而std::unique_ptr
几乎没用,不是吗?
第二件事是我想把这个指针传递给一个函数。这样做的正确方法是什么?
这个问题太宽泛了。 Herb Sutter曾写过an entire article about passing smart pointers to functions。这是一篇很长的文章,也有很多有趣的用户评论。你一定要读它。以下是Sutter的指南:
除非您愿意,否则不要将智能指针作为函数参数传递 使用或操纵智能指针本身,例如共享或 转让所有权。
首选按值,*或&amp;而不是智能指针传递对象。
使用按值
unique_ptr
参数表达“接收器”功能。
仅使用非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
的析构函数。
答案 1 :(得分:-1)
返回智能指针是正常的,直到您决定需要将其保存在不同类型的智能指针中。我只是返回一个原始指针,让调用者决定它想用它做什么。在你的情况下,std :: move是不必要的。
要将它传递给函数,请将函数参数设为const T&amp;并在智能指针上使用解除引用运算符。
void someFunction(const T& t)
{
}
std::unique_ptr<T> t = ...;
SomeFunction(*t);