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。
構造函數中拋出異常,可能會使對象部分構造,隨之就有可能導致資源洩漏或不一致的對象狀態,所以應避免在構造函數中拋出異常。