说明
类的构造函数抛出异常,不会调用该类的析构函数,资源的释放原则是编译器申请的编译器负责,程序员申请的程序员负责。 
在实验代码中,子类Except的构造函数抛出异常,则Base和mMember1的构造函数是编译器调用,因此编译器会调用它们的析构函数,而mMember2由程序员主动使用new生成,因此需要程序员主动使用delete。
解决方法:
- 在构造函数中使用try...catch结构
- 使用类包装资源申请,如auto_ptr。
实验代码
- /** 
-  * @file constructor_exception.cpp
-  * @brief 测试构造函数异常引起的行为
-  * @copyright public domain
-  */
- #include <iostream>
- #include <exception>
- #include <memory>
- class Base {
- public:
- Base() { std::cout << "Base()" << std::endl; }
- virtual ~Base() { std::cout << "~Base()" << std::endl; }
- };
- class Member {
- public:
- Member(int id):mId(id) { std::cout << "Member():" << mId << std::endl; }
- virtual ~Member() { std::cout << "~Member()" << mId << std::endl; }
- protected:
- int mId;
- };
- class Except : public Base {
- public:
- Except() : mMember1(1), mMember2(NULL) { 
- std::cout << "Except() enter" << std::endl; 
- mMember2 = new Member(2);
- mMember3.reset(new Member(3));
- throw std::exception();
- std::cout << "Except() leave" << std::endl; 
- }
- virtual ~Except() { 
- delete mMember2;
- std::cout << "~Except()" << std::endl; 
- }
- protected:
- Member mMember1;
- Member *mMember2;
- std::auto_ptr<Member> mMember3;
- };
- int main() {
- try {
- Except e;
- } catch (std::exception& e) {
- std::cout << e.what() << std::endl;
- }
- return 0;
- }
运行及结果
$ g++ constructor_exception.cpp 
$ ./a.out 
Base()
Member():1
Except() enter
Member():2
Member():3
~Member()3
~Member()1
~Base()
std::exception