第七色在线视频,2021少妇久久久久久久久久,亚洲欧洲精品成人久久av18,亚洲国产精品特色大片观看完整版,孙宇晨将参加特朗普的晚宴

為了賬號安全,請及時綁定郵箱和手機(jī)立即綁定

沒有學(xué)不會的C++:異常處理和析構(gòu)函數(shù)

標(biāo)簽:
C++

C++ 对待异常处理有两个规则

  1. 如果在 try...catch 中有异常抛出,则在 catch 执行前,会先将 try 语句块对应的栈清空
  2. C++ 不允许在同一个 try...catch 中处理1个以上的异常,如果发生此种情况,程序就会崩溃

为便于理解,我们先来看一个例子

class Dog {
public:
	string name;
	Dog(string name) {this->name = name; cout << name << " is born.\n"; }
    ~Dog() { cout << name << " is destroied.\n"; }
    
    void bark() { cout << name << " is barking.\n"; }
};

int main() {
    try {
        Dog dog1("Henry");
        Dog dog2("Bob");
        throw 20;
        dog1.bark();
        dog2.bark();
    } catch (int e) {
        cout << e << " is caught" << endl;
    }
}

/*
 * output:
 * Henry is born.
 * Bob is born.
 * Bog is destroied.
 * Henry is destroied.
 * 20 is caught
 */

从上面的例子可以看出,catch 语句块在两个局部对象析构完成后才执行,意味着在异常被捕获之前,try 代码块中的栈需要被清理。

我们把上面代码稍作修改,把 throw 语句放到析构函数中,看下会发生什么

class Dog {
    public:
        string name;
        Dog(string name) {this->name = name; cout << name << " is born.\n"; }
        ~Dog() { cout << name << " is destroied.\n"; throw 20;}

        void bark() { cout << name << " is barking.\n"; }
};

int main() {
    try {
        Dog dog1("Henry");
        Dog dog2("Bob");
        dog1.bark();
        dog2.bark();
    } catch (int e) {
        cout << e << " is caught" << endl;
    }
}

/* Output: 
 * Henry is born.
 * Bob is born.
 * Henry is barking.
 * Bob is barking.
 * Bob is destroied.
 * Henry is destroied.
 * libc++abi.dylib: terminating with uncaught exception of type int
 * [1]    51549 abort      ./exception
 */

可以看到程序崩溃了,崩溃原因是 terminating with uncaught exception of type int :异常没有被处理。我们来分析下其中的原因,在 try 中,我们定义了两个对象,并按照顺序调用了它们的 bark 接口,随后离开 try 代码块,此时,编译器会自动释放这两个局部对象,调用它们的析构函数,因为栈的特性是后进先出,所以先析构 Bob,在执行 Bob 的析构函数时,抛出了异常,但此时并不会立即执行 catch 语句块,根据上文提到的第一条规则:「在 catch 执行前,需要先清理 try 中的堆栈」。于是 Henry 也被析构了,这让 try 语句块中抛出了 2 个异常,直接导致了程序的崩溃。

找到上述程序崩溃的元凶后,我们便学到了一条宝贵的 C++ 经验:

不要在析构函数中抛出异常。

因为如果你的析构函数中有异常抛出的话,你便无法控制 try 语句中抛出来的异常数量——这将是一场灾难。

为了不在析构函数中抛出异常,一般有两种做法:

  1. 在析构函数内部捕获异常,防止异常被抛出,例如下面的代码

    ~Dog {
        try {
            // may throw exception
        } catch (MyException e) {
            // Catch exception
        } catch (...) {
            // 尽量不要使用 ... 来捕获异常
        }
    }
    

    虽然这样做,你的析构函数再不会抛出异常了,但却带来了一些隐患,即你使用了 (...) 来捕获异常,这种代码没有任何用处(它无法输出有效的异常信息),同时由于它会捕获一切异常,于是会将一些必要的程序缺陷掩盖起来,而不是“尽早的暴露问题”。所以在这里,我们学到的第二条经验是:

    不要使用 (...) 来捕获异常

  2. 保持析构函数简洁,将可能导致异常的代码移到其他的函数中。这也是推荐的做法。

参考

點擊查看更多內(nèi)容
TA 點贊

若覺得本文不錯,就分享一下吧!

評論

作者其他優(yōu)質(zhì)文章

正在加載中
  • 推薦
  • 評論
  • 收藏
  • 共同學(xué)習(xí),寫下你的評論
感謝您的支持,我會繼續(xù)努力的~
掃碼打賞,你說多少就多少
贊賞金額會直接到老師賬戶
支付方式
打開微信掃一掃,即可進(jìn)行掃碼打賞哦
今天注冊有機(jī)會得

100積分直接送

付費專欄免費學(xué)

大額優(yōu)惠券免費領(lǐng)

立即參與 放棄機(jī)會
微信客服

購課補(bǔ)貼
聯(lián)系客服咨詢優(yōu)惠詳情

幫助反饋 APP下載

慕課網(wǎng)APP
您的移動學(xué)習(xí)伙伴

公眾號

掃描二維碼
關(guān)注慕課網(wǎng)微信公眾號

舉報

0/150
提交
取消