我在C++11中使用一个工厂模式,它位于我的main()函数的范围内,调用如下所示:
histogram_requests -> AddNewPostfix( Postfix_factory :: get_postfix( "Layers", ntuple_reader ) );Postfix_factory::get_postfix()是一个静态成员函数,返回一个std ::unique_ptr< Postfix>。一个示例返回值是:
return std :: move( std :: unique_ptr<Postfix>( new Layers_postfix( ntuple_reader_p ) ));我的第一个问题是这样做是否有效?返回的指针是否在我的main()作用域的末尾被销毁了?
第二件事是,我想把这个指针传递给一个函数。正确的做法是什么?当我将AddNewPostFix()的参数类型设置为std::unique_ptr或std::unique_ptr&&但作为简单引用失败时,我的程序就会编译。我不想让我的AddNewPostFix()不小心删除指针中的数据,但我不确定这些数据是否安全。有人能告诉我如何正确和安全地做这件事吗?
发布于 2015-11-07 15:26:19
返回std ::move( std ::unique_ptr(新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将是非常无用的,不是吗?
第二件事是,我想把这个指针传递给一个函数。正确的做法是什么?
这个问题太宽泛了。赫伯·萨特曾经写过关于传递智能指针到函数的整篇文章。这是一篇很长的文章,也有有趣的用户评论。你绝对应该读一读。以下是萨特的指导方针:
不要将智能指针作为函数参数传递,除非您希望使用或操作智能指针本身,例如共享或传输所有权。
更喜欢按值、*或&,而不是通过智能指针传递对象。
使用
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的析构函数。
发布于 2015-11-07 14:21:09
返回智能指针是可以的,直到您决定需要将其保存在不同类型的智能指针中。我只需返回一个原始指针,并让调用方决定它要使用它做什么。在您的例子中,std::move是不必要的。
若要将其传递给函数,请将函数参数设为const &并在智能指针上使用dereference操作符。
void someFunction(const T& t)
{
}
std::unique_ptr<T> t = ...;
SomeFunction(*t);https://stackoverflow.com/questions/33583702
复制相似问题