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

C++14智能指针输出疑问:为何呈现该输出结果?

为什么用std::unique_ptr<Base>指向Derived对象时,Derived的析构函数没有被调用?

先把你的代码贴出来方便分析:

class Base { 
public: 
    Base() { std::cout << "Base::ctor" << std::endl; } 
    ~Base() { std::cout << "Base::dtor" << std::endl; } 
}; 

class Derived : public Base { 
public: 
    Derived() { std::cout << "Derived::ctor" << std::endl; } 
    ~Derived() { std::cout << "Derived::dtor" << std::endl; } 
}; 

int main(int argc, char** argv){ 
    std::unique_ptr<Base> b = std::make_unique<Derived>(); 
}

运行这段代码后,输出确实是:

Base::ctor
Derived::ctor
Base::dtor

咱们一步步拆解原因:

构造阶段的输出是正常的

当创建Derived对象时,C++的构造顺序是固定的:

  • 先调用基类Base的构造函数,所以先输出Base::ctor
  • 再调用派生类Derived的构造函数,输出Derived::ctor
    这部分完全符合C++的对象初始化规则,没有问题。

析构阶段的问题核心:缺少虚析构函数

问题出在对象销毁的环节:
std::unique_ptr<Base>在main函数结束时会自动销毁它指向的对象,但因为Base的析构函数没有声明为虚函数,C++的静态绑定机制会让编译器只调用Base的析构函数,跳过Derived的析构逻辑。

在C++里有个关键规则:如果需要通过基类指针/智能指针操作派生类对象,基类的析构函数必须声明为virtual,这样才能触发多态析构——销毁对象时会先调用派生类的析构函数,再调用基类的析构函数,保证对象的所有部分都被正确清理。

如果基类析构函数不是虚函数,通过基类指针删除派生类对象属于未定义行为,大多数编译器的表现就是只调用基类的析构函数,这就是你只看到Base::dtor的原因。

修正方案

只需要把Base的析构函数改成虚函数就行:

class Base { 
public: 
    Base() { std::cout << "Base::ctor" << std::endl; } 
    virtual ~Base() { std::cout << "Base::dtor" << std::endl; } // 声明为虚析构
}; 

此时再运行代码,输出就会变成正确的析构顺序:

Base::ctor
Derived::ctor
Derived::dtor
Base::dtor

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.25 07:10:24