說明
類的構造函數拋出異常,不會調用該類的析構函數,資源的釋放原則是編譯器申請的編譯器負責,程序員申請的程序員負責。
在實驗代碼中,子類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