当构造函数在执行过程中抛出异常,C++ 会负责清理在异常发生前已经成功构造的对象。具体来说,只有那些已经完成构造的成员变量和基类的析构函数会被调用。这是为了防止资源泄漏。
举一个例子来说明这一点:
cpp#include <iostream> #include <stdexcept> class A { public: A() { std::cout << "A 构造" << std::endl; } ~A() { std::cout << "A 析构" << std::endl; } }; class B { public: B() { std::cout << "B 构造" << std::endl; } ~B() { std::cout << "B 析构" << std::endl; } }; class C { public: C() { std::cout << "C 构造" << std::endl; throw std::runtime_error("在 C 中抛出异常"); } ~C() { std::cout << "C 析构" << std::endl; } }; class Test { A a; B b; C c; public: Test() { std::cout << "Test 构造" << std::endl; } ~Test() { std::cout << "Test 析构" << std::endl; } }; int main() { try { Test t; } catch (const std::exception &e) { std::cout << "捕获异常: " << e.what() << std::endl; } return 0; }
在这个例子中,Test
类包含三个成员:A a
,B b
,和C c
。当尝试构造 Test
类的对象时:
- 首先构造成员
A a
,成功后输出 "A 构造"。 - 接着构造成员
B b
,成功后输出 "B 构造"。 - 然后尝试构造成员
C c
,在构造过程中抛出异常,并输出 "C 构造" 和 "在 C 中抛出异常"。
因为 C c
的构造过程中发生了异常,它的析构函数不会被调用,因为它从未成功完成构造。但是,对于已经成功构造的 A a
和 B b
,它们的析构函数会被依次调用,输出 "B 析构" 和 "A 析构"。
这个机制确保了在构造过程中已经分配的资源能够被正确回收,防止资源泄漏。
2024年6月29日 12:07 回复