C++異常剖析

什么是異常?

????????在程序運行的過程中,我們不可能保證我們的程序百分百不出現異常和錯誤,那么出現異常時該怎么報錯,讓我們知道是哪個地方錯誤了呢?
????????C++中就提供了異常處理的機制。

一、異常處理的關鍵字

(1)throw: 當問題出現時,程序會拋出一個異常。這是通過使用 throw 關鍵字來完成的。
(2)catch: 在您想要處理問題的地方,通過異常處理程序捕獲異常。catch 關鍵字用于捕獲異常。
(3)try:try 塊中的代碼標識將被激活的特定異常。它后面通常跟著一個或多個 catch 塊(至少要跟一個)。

????????當被try的括號包圍的代碼塊(我們可稱之為保護代碼)出現異常時,就會拋出異常,catch塊的代碼就會捕獲異常并執行catch包圍的代碼塊。因為異常也可以有不同的種類,所以我們可以在try后面跟著多個catch塊,捕獲不同的異常,如下:

try
{// 保護代碼
}
catch( ExceptionName1 e1 )//第一種異常
{// catch 塊
}
catch( ExceptionName2 e2 )//第二種異常
{// catch 塊
}
catch( ExceptionName3 eN )//第三種異常
{// catch 塊
}

二、捕獲異常

????????使用 throw 語句可以在代碼塊中的任何地方拋出異常。
????????throw 語句的操作數可以是任意的表達式,表達式的結果的類型決定了拋出的異常的類型。
如下:

????????可以看到,我們拋出的是一串字符串,所以編譯器報錯的信息說異常類型是char(其實是const char*,但它簡寫了)。

????????實際我們編程的時候,我們肯定不希望編譯器就只給我說異常類型是char*就完了。我們還希望把它打印出來,讓我們看得到"出現了除數為0的錯誤",這就需要捕獲異常。

#include <iostream>
using namespace std;
double division(double a, double b)
{try{if (b == 0){throw "出現了除數為0的錯誤";//throw關鍵字拋出錯誤類型 const char*}}catch (const char* error_string)//捕獲const char*類型的錯誤{cout << error_string << endl;//打印它}return (a / b);
}
int main()
{cout << division(1, 0);
}

????????可見,有了try和catch后,程序不會在遇到錯誤時崩潰終止,而是會處理它,然后繼續運行。
所以這個程序依然能輸出計算結果inf(無限大),但是在此之前也打印了報錯信息。
總之,利用異常處理機制,我們就可以在程序運行時處理異常,大大減少程序崩潰的概率。
你在生活中經常遇到軟件閃退的問題,十有八九沒有做好異常處理。

三、C++標準庫自帶的異常類型

下表是對上面層次結構中出現的每個異常的說明:

std::exception 該異常是所有標準 C++ 異常的父類。 std::bad_alloc 該異常可以通過 new 拋出。
std::bad_cast 該異常可以通過 dynamic_cast 拋出。 std::bad_typeid 該異常可以通過 typeid
拋出。 std::bad_exception 這在處理 C++ 程序中無法預期的異常時非常有用。
std::logic_error 理論上可以通過讀取代碼來檢測到的異常。
std::domain_error 當使用了一個無效的數學域時,會拋出該異常。
std::invalid_argument 當使用了無效的參數時,會拋出該異常。
std::length_error 當創建了太長的std::string 時,會拋出該異常。
std::out_of_range 該異常可以通過方法拋出,例如 std::vector 和std::bitset<>::operator。
std::runtime_error 理論上不可以通過讀取代碼來檢測到的異常。
std::overflow_error 當發生數學上溢時,會拋出該異常。
std::range_error 當嘗試存儲超出范圍的值時,會拋出該異常。
std::underflow_error 當發生數學下溢時,會拋出該異常。

四、異常規格說明

異常規格說明的目的是為了讓函數使用者知道該函數可能拋出那些異常,可以再函數的聲明中列出這個函數可能拋出的所有異常類型,例如:

viod fun() throw(A,B,C,D);

????????throw后面的括號內,必須寫出會拋出的異常的類型,如果括號里面是空的,說明這個函數不會拋出任何異常。
????????如果你不聲明throw(A,B,C,D),那么編譯器就會認為這個函數什么異常都可能會拋出。
????????異常規范聲明可以讓編譯器知道可能會拋出的異常有哪些,就可以提升編譯速度和給編譯器更多的優化空間,讓你的代碼性能更高,也可以讓其他程序員了解你這段代碼可能會產生的異常,提高代碼可讀性。

五、noexcept關鍵字

在C++11中新增了noexcept關鍵字以表示這個函數不會拋出某種異常。并且可以阻止異常的傳播。

無條件的noexcept關鍵字

當我們聲明的noexcept關鍵字無條件時,表示這個函數中所的所有代碼都不會產生異常,如下:

void fun() noexcept; //C++11
void fun() noexcept(); //也可以寫成這樣,等價的
void fun() noexcept(...); //也可以寫成這樣,等價的
void fun() noexcept(true); //也可以寫成這樣,等價的
有條件的noexcept關鍵字
void fun(Type& x, Type& y) noexcept(noexcept(noexcept(fun1()),noexcept(fun2()));
//表示fun函數內會調用到的fun1函數和fun2函數都不會拋出異常,但不保證其他代碼不會拋出異常

什么時候我們需要noexcept關鍵字?
????????使用noexcept表明函數或操作不會發生異常,會給編譯器更大的優化空間。然而,并不是加上noexcept就能提高效率。
以下情形鼓勵使用noexcept:

(1)移動構造函數(move constructor)
(2)移動分配函數(move assignment)
(3)析構函數(destructor)。這里提一句,在新版本的編譯器中,析構函數是默認加上關鍵字noexcept的。下面代碼可以檢測編譯器是否給析構函數加上關鍵字noexcept。
(4)葉子函數(Leaf Function)。葉子函數是指在函數內部不分配棧空間,也不調用其它函數,也不存儲非易失性寄存器,也不處理異常。
最后強調一句,在不是以上情況或者沒把握的情況下,不要輕易使用noexcept。

六、定義新的異常類型

只有C++標準庫自帶的異常類型肯定是不夠用的,我們實際工作中還需要根據項目需求定義新的異常類型。

#include <iostream>
#include <exception>
using namespace std;
class DivisionZeroException :public exception//基于exception類定義新的異常類型除以0導致的異常類
{
public://這里重載了父類的虛函數what()//throw ()的括號里面沒有東西,這表示這個函數不會拋出任何異常//const 是常量的關鍵字,常量在定義后無法被修改const char* what() const throw (){return "出現了除以0的錯誤\n";}
};
double division(double a, double b)
{try{if (b == 0){DivisionZeroException e;throw e;//throw關鍵字拋出錯誤類型DivisionZeroException}}catch (DivisionZeroException e)//捕獲const char*類型的錯誤{cout<<e.what();//打印什么異常了}return (a / b);
}
int main()
{cout << division(1, 0);
}
出現了除數為0的錯誤
inf

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/207829.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/207829.shtml
英文地址,請注明出處:http://en.pswp.cn/news/207829.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

聯想電腦重裝系統Win10步驟和詳細教程

聯想電腦擁有強大的性能&#xff0c;很多用戶辦公都喜歡用聯想電腦。有使用聯想電腦的用戶反映系統出現問題了&#xff0c;想重新安裝一個正常的系統&#xff0c;但是不知道重新系統的具體步驟。接下來小編詳細介紹給聯想電腦重新安裝Win10系統系統的方法步驟。 推薦下載 系統之…

Codeforces Round 913 (Div. 3) (A-G)

后天就是 I C P C ICPC ICPC杭州站了&#xff0c;今天把之前做的 d i v 3 div3 div3題補一下&#xff0c;打完這場杭州站這賽季除了 E C F i n a l EC\,\,Final ECFinal就結束了&#xff0c;以后應該要多打 c f cf cf比賽練習保持手感&#xff0c;爭取下賽季沖一下金牌。 感覺這…

客廳顏值擔當:木飾面電視背景墻設計。福州中宅裝飾,福州裝修

你是否也為客廳的裝修設計而煩惱&#xff1f;現在&#xff0c;我為你帶來一款高顏值的木飾面電視背景墻設計&#xff0c;它將是你客廳的亮點所在。 1?? 確定背景墻的尺寸和位置 首先&#xff0c;你需要確定背景墻的尺寸和位置&#xff0c;這取決于你家電視的大小和放置位置。…

重新認識Word——多級列表和項目符號

重新認識Word——多級列表和項目符號 多級列表沒有運用標題樣式但標題格式統一 正式公本文書項目符號和自動編號項目符號自動編號軟回車重新起頭開始編號解決編號與文本距離過大問題 之前我們重新認識了Word里面的樣式&#xff0c;現在的情況就是&#xff0c;我的一些文字已經運…

Python Authlib庫:構建安全可靠的身份驗證系統

更多資料獲取 &#x1f4da; 個人網站&#xff1a;ipengtao.com 在現代應用程序中&#xff0c;安全性是至關重要的&#xff0c;特別是在處理用戶身份驗證時。Authlib庫為Python開發者提供了一套強大的工具&#xff0c;用于簡化和增強身份驗證和授權流程。本文將深入探討Authli…

因小失大,一個普通的postman多接口順序執行,讓項目癱瘓了一天

Runner的使用 postman不僅可以單獨運行某個接口&#xff0c;postman的 Runner模塊可以運行多個接口&#xff0c;可以實現真正意義上的自動化接口測試 Runner的主要功能如下 按順序調用接口&#xff0c;執行用例&#xff1b; 批量發送請求&#xff1b; 對接口數據進行參數化…

yarn和npm的區別

2023-12-8 yarn和npm的區別 是常用的包管理工具&#xff0c;用于node.js項目中安裝、管理、和更新依賴項 有以下幾個區別&#xff1a; 性能和速度&#xff1a;在包的安裝和下載方面&#xff0c;yarn比npm更快速&#xff0c;yarn通過并行下載和緩存等優化策略&#xff0c;可以…

DreamPlace 的下載安裝與使用

DreamPlace 是一款芯片放置工具&#xff0c;用于宏單元&#xff08;macro&#xff09;和標準單元&#xff08;Standard Cell&#xff09;的放置以及布線&#xff0c;并計算 HPWL、Overlap 等用于衡量芯片性能的參數。 一、環境 1. 系統環境&#xff1a;Ubuntu 20.04 DreamPla…

我獲取股票和期貨數據的常用函數

記錄一下獲取數據所使用的函數&#xff0c;以防止遺忘和方便查找。 # 獲取掘金的數據 # 需要打開并登陸掘金終端 def get_data_juejin(symbol"bu2112",start"2021-8-1",end"2021-8-30 23:00:00",frequency"1800s",fields"eob,sy…

MySQL視圖介紹與實驗練習

文章目錄 1. MySQL 中的視圖&#xff08;View&#xff09;簡介1.1 視圖的基本概念&#xff1a;1.2 創建視圖&#xff1a;1.3 查看視圖&#xff1a;1.4 更新視圖&#xff1a;1.5 刪除視圖&#xff1a;1.6 視圖的嵌套&#xff1a;1.7 權限管理&#xff1a;1.8 檢查視圖信息&#…

vuepress-----15、md用法進階

vuepress markdown說明文檔 https://www.vuepress.cn/guide/markdown.html # 示例&#xff1a;封裝countUp.js為Vue組件 https://github.com/inorganik/countUp.js https://inorganik.github.io/countUp.js/ # 安裝 yarn add countup.js# 創建vue文件 全局Vue組件存放位置…

web項目服務器后臺運行

阿里官方方法 在Linux系統的ECS實例內,當斷開SSH客戶端后,如何保持進程繼續運行的解決方案_云服務器 ECS-阿里云幫助中心 (aliyun.com)

<Linux>(極簡關鍵、省時省力)《Linux操作系統原理分析之文件管理(1)》(22)

《Linux操作系統原理分析之文件管理&#xff08;1&#xff09;》&#xff08;22&#xff09; 7 文件管理7.1 文件與文件系統7.1.1 文件7.1.3 文件系統及其功能 7.2 文件的組織結構7.2.1 文件的邏輯結構7.2.2 文件的物理結構一、順序結構&#xff08;順序文件或連續文件&#xf…

Java來實現二叉樹算法,將一個二叉樹左右倒置(左右孩子節點互換)

文章目錄 二叉樹算法二叉樹左右變換數據 今天來和大家談談常用的二叉樹算法 二叉樹算法 二叉樹左右變換數據 舉個例子&#xff1a; Java來實現二叉樹算法&#xff0c;將一個二叉樹左右倒置&#xff08;左右孩子節點互換&#xff09;如下圖所示 實現的代碼如下&#xff1a;以…

ECharts的顏色漸變

目錄 一、直接配置參數實現顏色漸變 二、使用ECharts自帶的方法實現顏色漸變 一、兩種漸變的實現方法 1、直接配置參數實現顏色漸變 橫向的漸變&#xff1a; //主要代碼 option {xAxis: {type: category,boundaryGap: false,data: [Mon, Tue, Wed, Thu, Fri, Sat, Sun]},yA…

云上巴蜀丨云軸科技ZStack成功實踐精選(川渝)

巴蜀——古政權必爭之地 不僅擁有優越的戰略位置 而且擁有豐富的自然資源&#xff0c;悠久的歷史文化 如今的川渝經濟、人口發展迅速 2023年前三季度&#xff0c;四川與重慶GDP增速均超過國家平均線&#xff0c;為6.5%為5.6% 川渝經濟發展帶動數字化發展浪潮 云軸科技ZSt…

打造專屬小程序,喬拓云模板平臺助力商家搶占先機

打造專屬小程序&#xff0c;喬拓云模板平臺助力商家搶占先機&#xff01;該平臺涵蓋全行業小程序模板&#xff0c;一鍵復制即可上線。 想要快速創建高效實用的小程序&#xff0c;喬拓云小程序模板開發平臺為您提供了解決方案&#xff01;我們為您提供一系列精心設計的小程序模板…

LeetCode Hot100 131.分割回文串

題目&#xff1a; 給你一個字符串 s&#xff0c;請你將 s 分割成一些子串&#xff0c;使每個子串都是 回文串 。返回 s 所有可能的分割方案。 回文串 是正著讀和反著讀都一樣的字符串。 方法&#xff1a;靈神-子集型回溯 假設每對相鄰字符之間有個逗號&#xff0c;那么就看…

[c++]—string類___深度學習string標準庫成員函數與非成員函數(string的增刪查改函數)

沉淀,沉淀,再沉淀. &#x1f469;&#x1f3fb;?&#x1f4bb;作者:chlorine &#x1f449;上一篇&#xff1a;string標準庫成員函數和非成員函數(上) 目錄 &#x1f36d;構造和析構的實現 &#x1f36d; string→c類型的字符串數組 &#x1f36d;operator[]類對象元素的訪…

c語言-動態內存管理

文章目錄 一、為什么會有動態內存管理二、申請內存函數1、malloc2、free3、calloc4、realloc 三、常見的動態內存的錯誤四、練習 一、為什么會有動態內存管理 1.我們一般的開辟空間方式&#xff1a; int a 0;//申請4個字節空間 int arr[10] { 0 };//申請40個字節空間2.這樣…