在this上调用析构函数后使用placement new重建对象是否合法?
关于C++类clear方法使用placement new实现的合法性说明
两种实现的行为判定
- 第一种实现确实是未定义行为:
调用this->~A()后,当前对象的生命周期已经正式结束,this指向的是已销毁的无效对象。此时执行*this = A()需要解引用this获得已销毁对象的左值,赋值操作的目标不存在,完全符合未定义行为的特征。 - 第二种placement new的实现在满足限定条件的前提下,是完全符合C++标准的合法行为,不属于未定义行为:
析构函数调用结束后,虽然原对象生命周期终止,但它占用的内存空间仍然是合法、对齐正确且大小足够容纳A类对象的。new (this) A()是标准的placement new语法,作用就是在指定的已分配内存地址上直接调用构造函数创建新对象,整个过程不需要对已经失效的this进行解引用访问,操作本身是合规的。
必须满足的前置限制条件
如果要使用这种实现,必须保证你的类满足以下所有要求,否则仍然会触发未定义行为:
- A类的默认构造函数不会抛出异常。如果构造过程抛出异常,原对象已经销毁、新对象未成功构造,当前内存会处于无效状态,后续所有访问都是UB。建议给A的默认构造函数加上
noexcept修饰符显式保证。 - A类不能包含
const修饰的非静态数据成员,也不能包含引用类型的非静态数据成员。C++标准规定这类对象在同地址重建后,原有的指针、引用和标识符不会自动绑定到新对象,后续访问会有问题。 - A类不会被其他类继承,或者这个
clear方法只会在最派生类的实例上调用。如果A是基类且析构函数不是虚函数,调用this->~A()只会销毁基类部分的资源,派生类部分的资源会泄漏,后续重建也只会构造基类部分,整个对象状态完全错误。 - 不存在通过
const限定的指针或引用修改当前对象的情况,避免违反const语义。
更推荐的替代实现
由于placement new的写法对使用者要求高、容易漏看限制条件触发问题,更推荐把初始化和释放逻辑抽离为独立的私有成员函数,写法更直观易维护:
class A { private: void init() { // 原本写在构造函数里的初始化逻辑 } void destroy() { // 原本写在析构函数里的资源释放逻辑 } public: A() { init(); } ~A() { destroy(); } void clear() { destroy(); init(); } // 其他成员函数 };
这种实现没有额外的限制条件,也完全符合你要复用析构和构造逻辑的需求,绝大多数场景下都比placement new的实现更合适。
内容的提问来源于stack exchange,提问作者DL33
相关产品推荐
相关产品推荐

