C++使用C++ 11分配shared_ptr(std :: shared_ptr):将shared_ptr初始化为临时变量仍然不好吗?

Ste*_* Lu 10 c++ pointers smart-pointers shared-ptr c++11

我正在阅读这个答案,作者提到了最佳实践:

避免使用未命名的shared_ptr临时值来保存输入; 要了解为什么这是危险的,请考虑以下示例:

void f(shared_ptr<int>, int); 
int g();

void ok() {
    shared_ptr<int> p(new int(2));
    f(p, g());
}

void bad() {
    f(shared_ptr<int>(new int(2)), g());
}
Run Code Online (Sandbox Code Playgroud)

函数ok遵循字母的准则,而bad构造临时shared_ptr,承认内存泄漏的可能性.由于函数参数是以未指定的顺序计算的,因此可以首先计算new int(2),g()second,如果g抛出异常,我们可能永远不会访问shared_ptr构造函数.<...>

通过使用boost/make_shared.hpp中定义的make_shared或allocate_shared工厂函数,也可以消除上述异常安全问题.这些工厂功能还通过合并分配提供了效率优势.

我想我会开始使用make_shared,但我想知道这一点建议是否仍然适用于C++ 11 shared_ptr.我问,因为我并不完全理解为什么投掷g()会阻止ctor被调用.

Nic*_*las 9

是的,C++ 11的shared_ptr工作方式相同.

我问,因为我并不完全理解为什么抛出g()会阻止ctor被调用.

你不懂什么?这是一个操作顺序问题,标准不需要特定的订单.让我们将语句解压缩为一系列表达式:

auto __temp = new int(2);
auto &&__temp2 = g();
auto __temp3 = shared_ptr<int>(__temp);
Run Code Online (Sandbox Code Playgroud)

你现在看到了问题吗?如果g抛出,则__temp3永远不会被初始化.因此,__temp将被泄露.

C++标准不要求以这种方式解压缩语句.但它也没有禁止它.允许编译器自由地对这些独立表达式进行排序,但它认为合适.