在成员函数内销毁this指向对象再重建是否属于定义行为?
在C++成员函数中先销毁自身再原地重建对象是否是定义行为?
先直接给结论:这段代码的行为是定义良好的,属于C++标准明确允许的操作。下面我一步步拆解为什么它合法:
首先聚焦代码里的核心操作:在do_smth()成员函数中,先通过this->~foo()显式调用当前对象的析构函数,再用placement new在this指向的内存位置重新构造一个foo对象。我们逐个环节分析合法性:
显式析构的合理性:对于
main里这种自动存储期的对象f,显式调用析构函数是允许的——这只会结束对象的生命周期,但不会释放它占据的内存(自动变量的内存会在作用域结束时由编译器自动回收)。不过要注意:析构后如果不重新构造,再访问原对象的任何成员都是未定义行为,而你的代码紧接着就做了重建,避开了这个坑。placement new的合法性:
this指向的内存区域仍然有效(因为f的作用域还没结束,内存没被回收),而且这块区域的大小、对齐方式完全匹配foo类型的要求(毕竟原本就是用来存foo对象的),所以在这里用placement new构造新的foo对象完全符合标准。重建后对象的访问合法性:当我们在原对象的存储位置上构造了同类型(忽略cv限定)的新对象后,原来的变量名
f会自动绑定到这个新对象上。所以main里调用f.print()时,访问的是重建后的新对象的x成员,这是完全合法的。
当然,这种操作也有一些需要警惕的边界情况:
- 如果原对象是
const限定的,或者包含引用成员、const成员,这种原地销毁重建的操作可能会触发未定义行为; - 析构完成后到重建完成前的这段时间,绝对不能访问
this指向的任何成员,否则也是未定义行为。
但回到你给出的代码,这些问题都不存在,所以整个行为是完全符合标准的定义行为。
内容的提问来源于stack exchange,提问作者Incomputable
相关产品推荐
相关产品推荐

