std :: make_shared()在C++中的变化17

Lin*_*gxi 27 c++ language-lawyer make-shared exception-safety c++17

cppref中,以下内容一直持续到C++ 17:

f(std::shared_ptr<int>(new int(42)), g())如果g在之后调用new int(42)并抛出异常,则可能导致内存泄漏的代码,同时f(std::make_shared<int>(42), g())是安全的,因为两个函数调用永远不会交错.

我想知道在C++ 17中引入了哪些更改使其不再适用.

lis*_*rus 20

所述P0145R3纸(其已被接受为C++ 17)细化几个C的评价++结构,包括顺序

后缀表达式从左到右进行计算.这包括函数调用和成员选择表达式

具体而言,本文将以下文本添加到标准的5.2.2/4段:

后缀表达式在表达式列表中的每个表达式和任何默认参数之前进行排序.与参数初始化相关联的每个值计算和副作用以及初始化本身在每个值计算和与任何后续参数的初始化相关联的副作用之前被排序.

  • 哇,完全没有遵循C++ 17,这是一个几乎令人费解的重大改变!当然,如果我们都正确地完成了我们的工作,它应该对我们完全透明,但仍然......哇. (13认同)
  • 好吧,我认为这是改进的嵌套行为.因此我们保证,当`g()`发生时,_if_已经发生`new`,那么`shared_ptr`结构也是如此./sf/answers/2695111751/然而,`shared_ptr`构造和`g()`之间的顺序仍然未知. (4认同)
  • @lisyarus:我怀疑论证的评价顺序会因为gcc/clang使用从右向左而MSVC从左到右使用而有所改变,我怀疑是否会热衷于改变这一点; 很可能那里的软件依赖于他们当前的行为. (3认同)
  • 挂起,open-std.org页面摘要与您引用的论文文本不符.有人说订单现在是不确定的(未指定) - 这意味着评估不能交错(我认为在C++ 11中已经是这种情况).该论文本身确实使用了"后续"一词,这表明订单是相当确定的.这是什么! (2认同)
  • 我认为xskxzr在人类语言中更直接,更清晰地回答了我的问题,而不是神秘的标准文本,所以我会接受他的回答.不过,你的回答以及评论部分的讨论非常有用,值得投票:) (2认同)

xsk*_*xzr 17

函数参数的评估顺序由P0400R0更改.

在更改之前,函数参数的评估相对于彼此没有排序.这意味着g()可以将评估插入到评估中std::shared_ptr<int>(new int(42)),这会导致您引用的上下文中描述的情况.

在更改之后,函数参数的评估是不确定地排序的,没有交错,这意味着所有副作用都std::shared_ptr<int>(new int(42))发生在之前或之后g().现在考虑g()可能抛出的情况.

  • 如果所有副作用std::shared_ptr<int>(new int(42))发生在那之前g(),分配的内存将由析构函数解除分配std::shared_ptr<int>.

  • 如果所有的副作用std::shared_ptr<int>(new int(42))后,那些发生g(),甚至有没有内存分配.

在任何一种情况下,无论如何都没有内存泄漏.