智能指针技术疑问:派生类构造异常时基类部分是否创建?
问题:C++使用智能指针的场景中,派生类对象构造触发异常时,基类部分是否会被创建?
先直接给结论:是的,基类部分会被正常创建,并且当派生类构造过程抛出异常时,已经构造完成的基类会被自动析构。这是C++异常安全机制的核心规则之一,用来避免留下半构造的对象导致资源泄漏。
我们结合你提供的代码一步步拆解逻辑:
首先回忆C++类的构造执行顺序:
- 优先构造基类部分(按照继承声明的顺序)
- 接着构造类内的成员变量(按照成员在类中声明的顺序)
- 最后执行派生类构造函数的函数体
回到你的代码,当尝试创建Derived对象时:
- 第一步调用
Base::ctor,基类构造完成,控制台输出Base::ctor - 第二步执行初始化列表里的
new Member(),调用Member::ctor输出Member::ctor,随后抛出异常 - 此时
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




