在cppref中,在 C++17 之前,以下内容一直有效:
诸如此类的代码如果在调用之后并引发异常,
f(std::shared_ptr<int>(new int(42)), g())可能会导致内存泄漏,而这是安全的,因为两个函数调用永远不会交错。gnew int(42)f(std::make_shared<int>(42), g())
我想知道 C++17 中引入的哪个更改使这不再适用。
在cppref中,在 C++17 之前,以下内容一直有效:
诸如此类的代码如果在调用之后并引发异常,
f(std::shared_ptr<int>(new int(42)), g())可能会导致内存泄漏,而这是安全的,因为两个函数调用永远不会交错。gnew 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(),则甚至没有内存分配。
在任何一种情况下,无论如何都不会再次发生内存泄漏。