我们是否需要为分配"placement new" "simple POD classes"显式调用析构函数?

Do we need to explicitly call the destructor for the "simple POD classes" allocated with "placement new"?

本文关键字:classes POD 析构函数 调用 simple new 是否 placement 分配 我们      更新时间:2023-10-16

这里的"简单",我的意思是具有非虚拟空析构函数或 POD 类型的类。

典型例子:

char buffer[SIZE];
T *p = new(buffer) T;
...
p->~T();  // <---- always ?

如果我们不对p调用显式析构函数会发生什么?我不认为这是未定义的行为或内存泄漏。
重用buffer有问题吗?

从技术上讲,假设析构函数不释放在构造过程中获得的任何资源,则可能没有必要。

但是,考虑到非技术方面 - 代码的维护和演变 - 我会坚持最佳实践 - 构建的内容应该被破坏。要考虑的方案 - 如果将来某些更改将确定要放入析构函数中的相关代码怎么办?你会记得你一直破坏那种类型的物体吗?

对于 POD 类型或具有简单析构函数的类:否。对象的生存期将在释放或重用对象的存储时结束。如果您不想,则不必显式调用析构函数。

也就是说,没有理由不这样做。对于具有简单析构函数的类型,析构函数调用不会生成任何代码。

如果通过具有

"空"析构函数的类,您允许该类具有具有非平凡析构函数的成员或基类的可能性,那么如果您的程序依赖于调用的这些析构函数,则可能会获得未定义的行为。

请注意,用户提供的析构函数是非平凡析构函数,即使它是非虚拟的并且为空。尽管如此,您仍然可以通过简单地释放或重用其存储来结束使用此类析构函数结束对象的生存期,前提是您的程序不依赖于析构函数的任何副作用。(参见ISO/IEC 14882:2011的3.8 [basic.life]/4(

如果您的类处理某些资源(堆内存、句柄、计数器、互斥体...(或包含一些处理资源的字段,则如果不显式调用析构函数,则不会释放此资源。否则,没有任何破坏的麻烦。您可以将非析构类视为内存中的垃圾,并在同一位置自由构造新类。

是的,你必须显式调用析构函数(请记住 T 的副作用,即释放一些额外的内存(。此外,在使用放置 new 时,您必须小心内存对齐。

如果您愿意,可以重用缓冲区内存。

另请参阅 http://www.parashift.com/c++-faq-lite/dtors.html#faq-11.14