banner
cells

cells

为美好的世界献上 bug

Q015-關於構造函數拋出異常

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 類的成員變量 aa 調用 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

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

載入中......
此文章數據所有權由區塊鏈加密技術和智能合約保障僅歸創作者所有。