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
相关产品推荐
相关产品推荐

