You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

智能指针技术疑问:派生类构造异常时基类部分是否创建?

问题:C++使用智能指针的场景中,派生类对象构造触发异常时,基类部分是否会被创建?

先直接给结论:是的,基类部分会被正常创建,并且当派生类构造过程抛出异常时,已经构造完成的基类会被自动析构。这是C++异常安全机制的核心规则之一,用来避免留下半构造的对象导致资源泄漏。

我们结合你提供的代码一步步拆解逻辑:

首先回忆C++类的构造执行顺序:

  • 优先构造基类部分(按照继承声明的顺序)
  • 接着构造类内的成员变量(按照成员在类中声明的顺序)
  • 最后执行派生类构造函数的函数体

回到你的代码,当尝试创建Derived对象时:

  1. 第一步调用Base::ctor,基类构造完成,控制台输出Base::ctor
  2. 第二步执行初始化列表里的new Member(),调用Member::ctor输出Member::ctor,随后抛出异常
  3. 此时Derived的构造还未完成(连构造函数体都没进入),C++的异常处理机制会自动清理已构造完成的部分:
    • 由于Member的构造函数抛出异常,new表达式会自动释放为Member分配的内存(不会产生内存泄漏),且Member的析构函数不会被调用——因为对象根本没构造成功
    • 已经构造完成的Base部分会被调用析构函数,控制台输出Base::dtor

这段代码的运行输出会是:

Base::ctor
Member::ctor
Base::dtor

至于你提到的智能指针场景,比如用std::unique_ptr<Derived> ptr = std::make_unique<Derived>()创建对象,行为完全一致。make_unique内部会调用Derived的构造函数,当构造抛出异常时,智能指针会自动放弃对未完全构造对象的所有权,同时触发上述的基类析构逻辑,不会产生内存泄漏。

最后补充一个小建议:你的代码中用裸指针Member* m_管理成员存在风险——如果Member构造成功,但Derived构造函数体中抛出异常,m_指向的内存就会泄漏。推荐用智能指针管理成员,比如std::unique_ptr<Member> m_,这样即使构造过程出问题,智能指针也会自动释放资源,更符合异常安全要求。

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

火山引擎 最新活动