日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程语言 > c/c++ >内容正文

c/c++

C++异常详解

發(fā)布時(shí)間:2023/12/15 c/c++ 18 豆豆
生活随笔 收集整理的這篇文章主要介紹了 C++异常详解 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

1.對異常的幾種處理方式
1)調(diào)用abort()
abort()函數(shù)的原型位于頭文件cstlib中,其實(shí)現(xiàn)是向標(biāo)準(zhǔn)錯(cuò)誤流發(fā)送abnormal program termination(程序異常終止),然后終止程序。
示例如下:

#inclide<iostream> #inclide<cstlib> double hmean(double x,double y) {if(x==-y){std::cout<<"arguments are not valid\n";std::abort();}return 2*x*y/(x+y); } int main() {double x,y,z;while(std::cin>>x>>y){z=hmean(x,y);std::cout<<"result is "<<z<<std::endl;std::cout<<"next loop "<<std::endl;}return 0; }

2)返回錯(cuò)誤碼
使用一個(gè)bool值來標(biāo)記,運(yùn)行結(jié)果是成功,還是失敗。
示例如下:

#inclide<iostream> bool hmean(double x,double y,double &z) {if(x==-y){return false;}z= 2*x*y/(x+y);return true; } int main() {double x,y,z;while(std::cin>>x>>y){if(hmean(x,y,z)){std::cout<<"result is false!"<<std::endl;}else{std::cout<<"result is true!"<<std::endl;std::cout<<"result is "<<z<<std::endl;}std::cout<<"next loop "<<std::endl;}return 0; }

3)使用全局變量errno
出現(xiàn)異常時(shí)可以將全局變量errno設(shè)值,需要注意的是,要確保沒有其他的函數(shù)同時(shí)在使用這個(gè)全局變量

2.異常機(jī)制
涉及try,catch,throw關(guān)鍵字
示例代碼如下:

#inclide<iostream> double hmean(double x,double y) {if(x==-y){throw "arguments are not valid";}return 2*x*y/(x+y); } int main() {double x,y,z;while(std::cin>>x>>y){try{z = hmean(x,y);}catch(const char* s){std::cout<<s<<std::endl;std::cout<<"next loop "<<std::endl;continue;}std::cout<<"result is "<<z<<std::endl;std::cout<<"next loop "<<std::endl;}return 0; }

3.上面的示例中,我們拋出的是字符串,通常情況,我們會為每個(gè)可能出現(xiàn)的異常,定義一個(gè)異常類,當(dāng)出現(xiàn)異常時(shí),拋出該異常對象,catch塊對該異常對象進(jìn)行捕獲。
示例代碼如下:

#inclide<iostream> class bad_hmean { private:double x;double y; public:bad_hmean(int a=0,int b=0):x(a),y(b){}void mesg(); }; inline void bad_hmean::mesg() {std::cout<<"arguments are not valid "<<x<<" "<<y<<std::endl; } double hmean(double x,double y) {if(x==-y){throw bad_mean(x,y);}return 2*x*y/(x+y); } int main() {double x,y,z;while(std::cin>>x>>y){try{z = hmean(x,y);}catch(bad_hmean &hg){hg.mesg();std::cout<<"next loop "<<std::endl;continue;}std::cout<<"result is "<<z<<std::endl;std::cout<<"next loop "<<std::endl;}return 0; }

4.異常規(guī)范
我們看下面的兩行代碼
double hmean(int x,int y) throw(bad_thing)//可能拋出bad_thing異常
double hmean(int x,int y) throw()//不拋出異常
其中后面的throw()部分就是異常規(guī)范,指出該函數(shù)可能拋出的異常。
程序員來確定可能拋出的異常,這樣并不好。
在C++11中,已經(jīng)摒棄了該規(guī)范。

5.棧解退

棧解退是很重要的概念。為什么這么說呢,當(dāng)拋出異常后,程序終止,或被catch塊捕捉,我們必須要考慮內(nèi)存的釋放問題。

我們先看一下,正常函數(shù)是如何處理內(nèi)存釋放的。
函數(shù)調(diào)用時(shí),調(diào)用函數(shù)的指令的地址會放到棧中,函數(shù)的參數(shù)或局部變量也將被添加到棧中或堆中。
如果在其中又調(diào)用了函數(shù),則執(zhí)行同樣的操作。
當(dāng)函數(shù)結(jié)束以后,程序會跳到被調(diào)用時(shí)存儲的地址處,棧頂?shù)脑乇会尫?#xff0c;同時(shí)釋放其自動變量。
如果自動變量時(shí)類對象,則類的析構(gòu)函數(shù)將被調(diào)用。

當(dāng)函數(shù)出現(xiàn)異常時(shí),程序也將不斷釋放棧,直到找到一個(gè)與該異常相對應(yīng)的try塊的返回地址。
隨后,控制權(quán)將轉(zhuǎn)到塊尾的catch處理程序,而不是函數(shù)調(diào)用后面的第一條語句,這個(gè)過程稱為棧解退。
和正常函數(shù)調(diào)用不同的是,函數(shù)返回將處理該函數(shù)放在棧中的對象,而函數(shù)異常則處理,try塊和throw之間放在棧中的對象。
有了棧解退機(jī)制,引發(fā)異常后,也會釋放調(diào)用中間函數(shù)時(shí)棧中的對象。

我們看看下面的兩個(gè)例子:

void test1() {string mesg("hello");if(false)throw exception();return; }void test2() {double *ar = new double[n];if(false)throw exception();delete [] ar;return; }

對于test1,函數(shù)異常后,會進(jìn)行棧解退,string類析構(gòu)函數(shù)會被調(diào)用,占用的內(nèi)存將釋放。
對于test2,棧解退時(shí),將刪除棧中變量ar,但ar指向的內(nèi)存塊未釋放,并且不可訪問,會造成內(nèi)存泄漏的問題。此時(shí)要如何處理呢?
可以在引發(fā)異常的代碼塊中,捕獲該異常,釋放該內(nèi)存塊,然后重新引發(fā)異常。此時(shí),內(nèi)存塊就被釋放了。

void test2() {double *ar = new double[n];try{if(false)throw exception();}catch(exception &ex){delete[] ar;throw;}delete [] ar;return; }

6.關(guān)于catch塊

try {} catch(exception &ex) {}

注意catch塊中參數(shù)為引用類型。當(dāng)throw異常向上拋出時(shí),該異常對象會被釋放,此時(shí)catch塊接收的異常對象為原始異常對象的一個(gè)副本。
使用引用的目的是,基類引用可以執(zhí)行派生類對象。若不使用引用,則只能調(diào)用基類的特性。

7.C++標(biāo)準(zhǔn)異常庫
標(biāo)準(zhǔn)異常類exception在頭文件exception中定義,類含有一個(gè)名為what()的虛擬成員函數(shù)。從exception派生的類可以重新定義它。
C++庫定義了很多基于exception的異常類型,此處不再詳細(xì)介紹。

?

參考資料:《C++ Primer.Plus》 pp.616-642

總結(jié)

以上是生活随笔為你收集整理的C++异常详解的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。