最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

C++異常使用詳解(看這一篇就夠了)

 更新時間:2023年10月20日 10:36:07   作者:Insisting.  
C++中的異常是指在程序執(zhí)行過程中發(fā)生錯誤,導致程序無法正常運行的情況,下面這篇文章主要給大家介紹了關于C++異常使用的相關資料,文中通過代碼介紹的非常詳細,需要的朋友可以參考下

一、異常的概念

異常是一種處理錯誤的方式,當一個函數發(fā)現自己無法處理的錯誤時就可以拋出異常,讓函數的直接或間接的調用者處理這個錯誤。

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

語法:

try
{
    // 保護的標識代碼
}
catch( ExceptionName e1 )
{
    // catch 塊
}
catch( ExceptionName e2 )
{
    // catch 塊
}
catch( ExceptionName eN )
{
    // catch 塊
}

二、異常的使用

1.異常的拋出和捕獲原則

1.異常是通過拋出對象而引發(fā)的,該對象的類型決定了應該激活哪個catch的處理代碼。

#define _CRT_SECURE_NO_WARNINGS 1
#include<iostream>
#include<vector>
using namespace std;

double Division(int a, int b)
{
	//當b == 0時拋出異常
	if (b == 0)
		throw "Division by zero condition!";
		//throw 1;
	else
		return ((double)a / (double)b);
}

void func()
{
	int len, time;
	cin >> len >> time;
	cout << Division(len, time) << endl;
}

int main()
{
	try {
		func();
	}
	catch (const char* errmsg)
	{
		cout << errmsg << endl;
	}
	catch (const int errmsg)
	{
		cout << errmsg << endl;
	}
	return 0;
}

當拋出的異常時char* 類型時

在這里插入圖片描述

當拋出異常換成整形時

在這里插入圖片描述

2.被選中的處理代碼是調用鏈中與該對象類型匹配且離拋出異常位置最近的那一個

#define _CRT_SECURE_NO_WARNINGS 1
#include<iostream>
#include<vector>
using namespace std;

double Division(int a, int b)
{
	try
	{
		//當b == 0時拋出異常
		if (b == 0)
			throw "Division by zero condition!";
		else
			return ((double)a / (double)b);
	}
	catch(const char* errmsg)
	{
		cout << "Division:" << errmsg << endl;
	}
}

void func()
{
	int len, time;
	cin >> len >> time;
	cout << Division(len, time) << endl;
}

int main()
{
	try {
		func();
	}
	catch (const char* errmsg)
	{
		cout << errmsg << endl;
	}
	catch (const int errmsg)
	{
		cout << errmsg << endl;
	}
	return 0;
}

3.拋出異常對象后,會生成一個異常對象的拷貝,因為拋出的異常對象可能是一個臨時對象,所以會生成一個拷貝對象,這個拷貝的臨時對象會在被catch以后銷毀。(這里的處理類似于函數的傳值返回)

4.catch(…)可以捕獲任意類型的異常,問題是不知道異常錯誤是什么。

void fun1()
{
	throw "錯誤";
}

int main()
{
	try {
		fun1();
	}
	catch(const int errmsg)
	{
		cout << errmsg;
	}
	catch (...)
	{
		cout << "未知錯誤" << endl;
	}
}

5.實際中拋出和捕獲的匹配原則有個例外,并不都是類型完全匹配,可以拋出的派生類對象,使用基類捕獲,這個在實際中非常實用,以后主要用到的也是這種方式

2.在函數調用鏈中異常棧展開匹配原則

1.首先檢查throw本身是否在try塊內部,如果是再查找匹配的catch語句。如果有匹配的,則調到catch的地方進行處理。
2.沒有匹配的catch則退出當前函數棧,繼續(xù)在調用函數的棧中進行查找匹配的catch。
3.如果到達main函數的棧,依舊沒有匹配的,則終止程序。上述這個沿著調用鏈查找匹配的catch子句的過程稱為棧展開。所以實際中我們最后都要加一個catch(…)捕獲任意類型的異常,否則當有異常沒捕獲,程序就會直接終止。
4.找到匹配的catch子句并處理以后,會繼續(xù)沿著catch子句后面繼續(xù)執(zhí)行。

3.異常規(guī)范

1.異常規(guī)格說明的目的是為了讓函數使用者知道該函數可能拋出的異常有哪些。 可以在函數的
后面接throw(類型),列出這個函數可能拋擲的所有異常類型
2.函數的后面接throw(),表示函數不拋異常。
3.若無異常接口聲明,則此函數可以拋擲任何類型的異常。

// 這里表示這個函數會拋出A/B/C/D中的某種類型的異常
void fun() throw(A,B,C,D);
// 這里表示這個函數只會拋出bad_alloc的異常
void* operator new (std::size_t size) throw (std::bad_alloc);
// 這里表示這個函數不會拋出異常
void* operator new (std::size_t size, void* ptr) throw();

// C++11 中新增的noexcept,表示不會拋異常
thread() noexcept;

4.異常安全

  • 構造函數完成對象的構造和初始化,最好不要在構造函數中拋出異常,否則可能導致對象不完整或沒有完全初始化
  • 析構函數主要完成資源的清理,最好不要在析構函數內拋出異常,否則可能導致資源泄漏(內存泄漏、句柄未關閉等)
  • C++中異常經常會導致資源泄漏的問題,比如在new和delete中拋出了異常,導致內存泄漏,在lock和unlock之間拋出了異常導致死鎖,C++經常使用RAII來解決以上問題。
#define _CRT_SECURE_NO_WARNINGS 1
#include<iostream>
#include<vector>
#include<windows.h>
using namespace std;

double Division(int a, int b)
{
	//當b == 0時拋出異常
	if (b == 0)
		throw "Division by zero condition!";
	else
		return ((double)a / (double)b);
}

void func()
{
	int* array = new int[10];
	int len, time;
	cin >> len >> time;
	cout << Division(len, time) << endl;
	cout << "delete []" << array << endl;
	delete[] array;
}

int main()
{
	try {
		func();
	}
	catch (const char* errmsg)
	{
		cout << errmsg << endl;
	}
	catch (const int errmsg)
	{
		cout << errmsg << endl;
	}
	return 0;
}

正常情況,沒有異常

有異常

如果出現了在new和delete中間拋出異?;蛘咧虚g的某個函數拋出異常,會導致程序直接跳轉到catch的地方而無法實現delete,出現內存泄漏

5.異常的重新拋出

有可能單個的catch不能完全處理一個異常,在進行一些校正處理以后,希望再交給更外層的調用鏈函數來處理,catch則可以通過重新拋出將異常傳遞給更上層的函數進行處理。

double Division(int a, int b)
{
    // 當b == 0時拋出異常
    if (b == 0)
    {
        throw "Division by zero condition!";
    }
    return (double)a / (double)b;
}
void Func()
{
    // 這里可以看到如果發(fā)生除0錯誤拋出異常,另外下面的array沒有得到釋放。
    // 所以這里捕獲異常后并不處理異常,異常還是交給外面處理,這里捕獲了再重新拋出去。
    int* array = new int[10];
    try 
    {
        int len, time;
        cin >> len >> time;
        cout << Division(len, time) << endl;
    }
    catch (...)
    {
        cout << "delete []" << array << endl;
        delete[] array;
        throw; // 重新拋出異常,且內容不變
    }
    // ...
    cout << "delete []" << array << endl;
    delete[] array;
}
int main()
{
    try
    {
        Func();
    }
    catch (const char* errmsg) // 捕獲Func重新拋出的異常
    {
        cout << errmsg << endl;
    }
    return 0;
}

三、異常的優(yōu)缺點

異常的優(yōu)點

  • 異常對象定義好了,相比錯誤碼的方式可以清晰準確的展示出錯誤的各種信息,甚至可以包含堆棧調用的信息,這樣可以幫助更好的定位程序的bug。
  • 返回錯誤碼的傳統(tǒng)方式有個很大的問題就是,在函數調用鏈中,深層的函數返回了錯誤,那么我們得層層返回錯誤,最外層才能拿到錯誤.
  • 很多的第三方庫都包含異常,比如boost、gtest、gmock等等常用的庫,那么我們使用它們也需要使用異常。
  • 很多測試框架都使用異常,這樣能更好的使用單元測試等進行白盒的測試。
  • 部分函數使用異常更好處理,比如構造函數沒有返回值,不方便使用錯誤碼方式處理。比如T&operator這樣的函數,如果pos越界了只能使用異?;蛘呓K止程序處理,沒辦法通過返回值表示錯誤。

異常的缺點

  • 異常會導致程序的執(zhí)行流亂跳,并且非常的混亂,并且是運行時出錯拋異常就會亂跳。這會導致我們跟蹤調試時以及分析程序時,比較困難。
  • 異常會有一些性能的開銷。當然在現代硬件速度很快的情況下,這個影響基本忽略不計。
  • C++沒有垃圾回收機制,資源需要自己管理。有了異常非常容易導致內存泄漏、死鎖等異常安全問題。這個需要使用RAII來處理資源的管理問題。學習成本較高。
  • C++標準庫的異常體系定義得不好,導致大家各自定義各自的異常體系,非常的混亂。
  • 異常盡量規(guī)范使用,否則后果不堪設想,隨意拋異常,外層捕獲的用戶苦不堪言。所以異常規(guī)范有兩點:一、拋出異常類型都繼承自一個基類。二、函數是否拋異常、拋什么異常,都使用 func()throw();的方式規(guī)范化。

總結 

到此這篇關于C++異常使用的文章就介紹到這了,更多相關C++異常內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!

相關文章

  • C語言數據結構之平衡二叉樹(AVL樹)實現方法示例

    C語言數據結構之平衡二叉樹(AVL樹)實現方法示例

    這篇文章主要介紹了C語言數據結構之平衡二叉樹(AVL樹)實現方法,結合實例形式分析了C語言平衡二叉樹的相關定義與使用技巧,需要的朋友可以參考下
    2018-01-01
  • c++快速排序詳解

    c++快速排序詳解

    快速排序總體思想:先找到一個樞軸,讓他作為分水嶺,通過一趟排序將待排序的記錄分割成兩部分,前面一部分都比樞軸小,后面一部分樞軸大,然后又分別對這兩部分記錄繼續(xù)進行遞歸的排序,達到整個序列有序的目的
    2017-05-05
  • C語言計算代碼執(zhí)行所耗CPU時鐘周期

    C語言計算代碼執(zhí)行所耗CPU時鐘周期

    本文給大家介紹的是使用C語言來計算代碼執(zhí)行所耗CPU時鐘周期的代碼,非常的簡單實用,不過要依托于sync,有需要的小伙伴自己參考下吧。
    2015-03-03
  • LoadLibrary深入案例詳解

    LoadLibrary深入案例詳解

    這篇文章主要介紹了LoadLibrary深入案例詳解,本篇文章通過簡要的案例,講解了該項技術的了解與使用,以下就是詳細內容,需要的朋友可以參考下
    2021-08-08
  • 帶頭結點單鏈表(詳解)

    帶頭結點單鏈表(詳解)

    這篇文章主要介紹了帶頭結點單鏈表?(詳解),需要的朋友可以參考下
    2023-07-07
  • C語言數據結構遞歸之斐波那契數列

    C語言數據結構遞歸之斐波那契數列

    這篇文章主要介紹了C語言數據結構遞歸之斐波那契數列的相關資料,希望通過本文能幫助到大家,讓大家理解掌握這部分內容,需要的朋友可以參考下
    2017-10-10
  • C語言實現數獨程序的示例代碼

    C語言實現數獨程序的示例代碼

    數獨是源自瑞士的一種數學游戲。是一種運用紙、筆進行演算的邏輯游戲。本文將利用C語言實現數獨程序,感興趣的小伙伴可以跟隨小編一起學習一下
    2023-03-03
  • C++中字符串全排列算法及next_permutation原理詳解

    C++中字符串全排列算法及next_permutation原理詳解

    這篇文章主要為大家詳細介紹了C++中字符串全排列(遞歸法)和(迭代法)以及next_permutation底層原理,文中的示例代碼講解詳細,感興趣的可以了解一下
    2023-02-02
  • 利用C語言實現單詞文本計數

    利用C語言實現單詞文本計數

    這篇文章主要為大家詳細介紹了如何編寫一個C語言程序,用于統(tǒng)計一個文本文件中每個單詞出現的次數,感興趣的小伙伴可以跟隨小編一起學習一下
    2024-11-11
  • C++實現LeetCode(199.二叉樹的右側視圖)

    C++實現LeetCode(199.二叉樹的右側視圖)

    這篇文章主要介紹了C++實現LeetCode(199.二叉樹的右側視圖),本篇文章通過簡要的案例,講解了該項技術的了解與使用,以下就是詳細內容,需要的朋友可以參考下
    2021-08-08

最新評論

容城县| 桐柏县| 宁津县| 阿巴嘎旗| 佛坪县| 南乐县| 资中县| 六枝特区| 维西| 河间市| 安平县| 怀仁县| 厦门市| 襄垣县| 天镇县| 同仁县| 石林| 布拖县| 咸宁市| 泰宁县| 交口县| 冀州市| 甘孜县| 商河县| 二连浩特市| 孟连| 南召县| 馆陶县| 平武县| 文安县| 佛山市| 闻喜县| 资阳市| 奈曼旗| 濮阳县| 西平县| 楚雄市| 陵川县| 海阳市| 彭山县| 鸡泽县|