为什么不删除在C++ 11中具有带有副作用未定义行为的析构函数的对象?

sha*_*oth 9 c++ destructor memory-leaks undefined-behavior c++11

这个答案引用了C++ 11 Standard 3.8:

如果没有对析构函数的显式调用或者如果没有使用delete-expression(5.3.5)来释放存储,则不应该隐式调用析构函数,并且任何依赖于析构函数产生的副作用的程序都没有被定义行为.

关于析构函数未被调用的部分很清楚.现在假设跳过的析构函数具有应该影响程序行为的副作用.

为什么程序行为现在未定义?为什么不跳过副作用(因为没有调用析构函数)并且程序正常运行而没有应用副作用?

Gre*_*ill 5

重要的部分是该段的第一部分(强调我的):

程序可以通过重用对象占用的存储来结束任何对象的生命周期......

如果只是为没有调用析构函数的对象重用存储,那么就会得到未定义的行为.例如,对象可能已经启动了一个线程,或者已经注册了一个回调,或者一个外部组件可能期望该对象仍然存在的其他操作.

  • 我不同意.完整引用添加*或通过显式调用析构函数来获取具有非平凡析构函数*的类类型的对象.因此在这种情况下将调用析构函数. (2认同)

Mat*_* M. 1

你的问题没有意义。

\n\n
\n

为什么不会跳过副作用(因为未调用析构函数)并且程序正常运行而不应用副作用?

\n
\n\n

它们被跳过,因为它们会被析构函数触发并且尚未被调用。

\n\n

我的阅读:

\n\n
\n

并且任何依赖于析构函数生成的 side e\xef\xac\x80ects 的程序都具有 unde\xef\xac\x81ned 行为。

\n
\n\n

很简单,我是根据RAII来看待的。例子:

\n\n
#include "Object.hpp"\n\nstruct Manager: private boost::noncopyable {\n  union Raw {\n    char _[sizeof(Object)];\n    Object o;\n  };\n  static Raw raw;\n\n  Manager() { new (raw.o) Object(); }\n  ~Manager() { raw.o.~Object(); }\n};\n
Run Code Online (Sandbox Code Playgroud)\n\n

现在,如果我分配一个Manager,忘记销毁它,然后分配一个新的,我就会陷入困境,因为我Object用第二个创建的存储覆盖了第一个创建的存储,即使它仍然“活动”。这是未定义的行为。

\n