Q015#
#include <iostream>
#include <exception>
int x = 0;
class A {
public:
A() {
std::cout << 'a';
if (x++ == 0) {
throw std::exception();
}
}
~A() {
std::cout << 'A';
}
};
class B {
public:
B() {
std::cout << 'b';
}
~B() {
std::cout << 'B';
}
A a;
};
void foo() {
static B b;
}
int main() {
try {
foo();
} catch (std::exception &) {
std::cout << 'c';
foo();
}
}
答案#
點擊查看答案
acabBA解釋#
在 try 中調用 foo() 函數,該函數中定義了一個局部靜態變量 b。在構造 b 對象時,會先構造 B 類的成員變量 a,a 調用 A 對象的默認構造函數,輸出 a,然後對 x 進行判斷,因為是後置 ++(先使用後增加),所以判斷時 x == 0,執行拋出異常的操作 throw exception(),catch (std::exception &) 捕獲到該異常後輸出 c,並調用 foo() 函數,進入 foo() 函數,因為在 try 中執行該函數時,局部靜態變量 b 並未完成初始化,所以將再次對 b 進行初始化,先構造 B 類成員變量 a,調用 A 對象默認構造函數,輸出 a,然後對 x 進行判斷,當前 x != 0,所以不執行拋出異常的操作,成員變量 a 構造完成,開始調用 B 的默認構造函數,輸出 b,在程序終止後,局部靜態變量 b 開始析構,先調用 b 的析構函數,輸出 B,再調用成員變量 a 析構函數,輸出 A。
構造函數中拋出異常,可能會使對象部分構造,隨之就有可能導致資源洩漏或不一致的對象狀態,所以應避免在構造函數中拋出異常。