在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 中引入的哪个更改使这不再适用。
在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 中引入的哪个更改使这不再适用。
函数参数的评估顺序由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()
,则甚至没有内存分配。
在任何一种情况下,无论如何都不会再次发生内存泄漏。