UB是否可以在不破坏对象存储的情况下重新使用它?

时间:2013-11-25 16:06:59

标签: c++ memory-management c++11

给定非POD类型T

auto p = new T();
::new (p) T();
/* ... */
delete p;

这是UB,对吧?

显然我没有直接泄漏为第一个T分配的内存(如果它没有间接成员,那么我根本就没有泄漏任何东西),但它从来没有被破坏,这在我看来成为有活力的猫类生物所组成的星系自发毁灭的伟大候选人。

感谢@Xeo,嗯,在C ++休息室“启发”这个问题。

1 个答案:

答案 0 :(得分:21)

相反。

  

[C++11: 3.8/1]: 类型为T的对象的生命周期在以下时间结束:

     
      
  • 如果T是具有非平凡析构函数(12.4)的类类型,则析构函数调用将启动,或者
  •   
  • 对象占用的存储空间被重用或释放
  •   

显然,这是一个重复使用的案例。

  

[C++11: 3.8/4]: 程序可以通过重用对象占用的存储来结束任何对象的生命周期,或者通过显式调用析构函数来获取具有非平凡性的类类型的对象析构函数。 对于具有非平凡析构函数的类类型的对象,在重用或释放对象占用的存储之前,程序不需要显式调用析构函数; 但是,如果没有显式调用析构函数或者如果没有使用 delete-expression (5.3.5)来释放存储,则不应该隐式调用析构函数和任何程序这取决于析构函数产生的副作用具有未定义的行为。

所以,即使对于非POD类型T,它也是有效的 iff 程序中没有任何东西实际上依赖于析构函数正在做的事情。

这有点通风,但它可能会让你正在做的事情。


请注意,这种宽大做法扩展到一些稍微更离奇的案例:

  

[C++11: 3.8/9]:在存储位置创建一个具有静态,线程或自动存储持续时间的const对象占用的新对象,或者在这个const对象在其生命周期结束前占用的存储位置结果未定义的行为