You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

在基类上执行placement new前跳过派生类析构函数是否为UB?示例是否含UB?

C++对象生命周期与Placement New相关问题

问题1:在基类上执行placement new前跳过派生类的析构函数是否属于未定义行为(UB)?

是的,这明确属于未定义行为(UB)。C++标准规定,要在已存在对象的内存区域上构造新对象,必须先终止原对象的生命周期——也就是调用其析构函数(除非原对象是平凡可析构类型)。如果跳过派生类的析构函数直接在其内存上构造基类对象,派生类特有的成员资源(如堆内存、文件句柄等)会无法释放,同时对象的虚表、内部状态等会处于混乱状态,后续任何对该内存区域的操作都可能触发不可预测的结果。


问题2:以下示例代码是否存在错误(包含UB)?

示例代码:

struct Base
{
    virtual int transmogrify();
};
 
struct Derived : Base
{
    int transmogrify() override
    {
        // missing this->~Derived();?
        new(this) Base;
        return 2;
    }
};
 
int Base::transmogrify()
{
    // missing this->~Base();?
    new(this) Derived;
    return 1;
}

这段代码确实存在未定义行为,核心问题在于两处placement new都没有先终止原对象的生命周期:

  • 在Derived::transmogrify中,直接调用new(this) Base前,没有执行this->~Derived()来结束当前Derived对象的生命周期。此时原Derived对象的虚表等核心信息仍处于生效状态,直接覆盖内存会破坏对象模型,后续操作可能出现虚函数调用错误、资源泄漏等问题。
  • 在Base::transmogrify中,调用new(this) Derived前,没有执行this->~Base()来终止当前Base对象的生命周期。即便Base是抽象类,其对象(或Derived对象的基类部分)的生命周期未被正确终止就被覆盖,同样违反了C++对象生命周期的规则,属于UB。

另外需要注意:这种在虚函数内部重新构造对象的写法本身就极具风险,因为调用虚函数时对象正处于活跃状态,重新构造可能导致调用链异常、对象状态错乱等难以排查的问题。


内容的提问来源于stack exchange,提问作者xmllmx

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.12 22:06:06