An MSDN page about smart pointers包含有关在参数列表中创建智能指针的提升警告:
始终在单独的代码行上创建智能指针,从不在参数列表中创建智能指针,以便由于某些参数列表分配规则而不会发生细微的资源泄漏。
它所指的参数列表分配规则是什么?在什么情况下会发生资源泄漏?
答案 0 :(得分:8)
它指的是以不同顺序评估参数的可能性,例如
func(unique_ptr<MyClass>(new MyClass), a(), b());
如果评估顺序为:a()
,MyClass()
,b()
,则构建unique_ptr
,可能会发生b()
抛出,内存将会被泄露了。
安全措施(已在C ++ 14中添加并且效率更高)是使用make_unique
(假设MSVC并根据您的编译器版本,您可能必须自己定义一个或{{3 }})。这同样适用于shared_ptr
。
此外,
f(std::shared_ptr<int>(new int(42)), g())
等代码可以 如果g
引发异常,则会导致内存泄漏,因为可能会调用g()
在new int(42)
之后和shared_ptr<int>
的构造函数之前。这个f(std::make_shared<int>(42), g())
中没有出现,因为有两个函数 呼叫永远不会交错。
答案 1 :(得分:2)
如果你这样做:
func(shared_ptr<Foo>(new Foo), shared_ptr<Bar>(new Bar));
签名是:
void func(shared_ptr<Foo>, shared_ptr<Bar>);
如果其中一个构造函数抛出会发生什么?可能会发生new
成功调用一次然后另一个失败(您不知道哪一个将首先被调用)。如果发生这种情况,其中一个对象可能会被泄露,因为它从未被资源管理器持有。
您可以在此处阅读更多内容:http://www.gotw.ca/gotw/056.htm
答案 2 :(得分:1)
问题在于,如果你的函数有多个参数:
void func( const std::shared_ptr< MyFirstClass >& ptr, const MySecondClass& ref );
你可以这样调用这个函数:
func( std::shared_ptr< MyFirstClass >( new MyFirstClass ), MySecondClass() );
编译器可以自由发出代码,以任何顺序执行参数列表中的表达式。其中一些订单可能会有问题。例如,假设编译器决定发出首先执行的代码
new MyFirstClass
然后
MySecondClass()
最后是std :: shared_ptr&lt; MyFirstClass&gt; (传递第一步中在免费商店中分配的MyFirstClass实例的地址)。
到目前为止一切顺利。但是如果第二步抛出异常,那么shared_ptr永远不会被构造,并且你的免费存储分配MyFirstClass-instance永远丢失。