智能指针和参数列表分配规则

时间:2014-09-24 14:16:58

标签: c++ c++11 smart-pointers

An MSDN page about smart pointers包含有关在参数列表中创建智能指针的提升警告:

  

始终在单独的代码行上创建智能指针,从不在参数列表中创建智能指针,以便由于某些参数列表分配规则而不会发生细微的资源泄漏。

它所指的参数列表分配规则是什么?在什么情况下会发生资源泄漏?

3 个答案:

答案 0 :(得分:8)

它指的是以不同顺序评估参数的可能性,例如

func(unique_ptr<MyClass>(new MyClass), a(), b());

如果评估顺序为:a()MyClass()b(),则构建unique_ptr,可能会发生b()抛出,内存将会被泄露了。

安全措施(已在C ++ 14中添加并且效率更高)是使用make_unique(假设MSVC并根据您的编译器版本,您可能必须自己定义一个或{{3 }})。这同样适用于shared_ptr

看看take a look here

  

此外,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永远丢失。