欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

解析C++編程中異常相關(guān)的堆棧展開和throw()異常規(guī)范

 更新時間:2016年01月25日 17:38:25   投稿:goldensun  
這篇文章主要介紹了C++編程中異常相關(guān)的堆棧展開和throw()異常規(guī)范,throw()規(guī)范部分文中結(jié)合了C++11標(biāo)準(zhǔn)的新特性來講,需要的朋友可以參考下

C++ 中的異常和堆棧展開
在 C++ 異常機制中,控制從 throw 語句移至可處理引發(fā)類型的第一個 catch 語句。在到達 catch 語句時,throw 語句和 catch 語句之間的范圍內(nèi)的所有自動變量將在名為“堆棧展開”的過程中被銷毀。在堆棧展開中,執(zhí)行將繼續(xù),如下所示:
控制通過正常順序執(zhí)行到達 try 語句。執(zhí)行 try 塊內(nèi)的受保護部分。
如果執(zhí)行受保護的部分的過程中未引發(fā)異常,將不會執(zhí)行 try 塊后面的 catch 子句。執(zhí)行將在關(guān)聯(lián)的 try 塊后的最后一個 catch 子句后面的語句上繼續(xù)。
如果執(zhí)行受保護部分的過程中或在受保護的部分調(diào)用的任何例程中引發(fā)異常(直接或間接),則從通過 throw 操作數(shù)創(chuàng)建的對象中創(chuàng)建異常對象。(這意味著,可能會涉及復(fù)制構(gòu)造函數(shù)。)此時,編譯器會在權(quán)限更高的執(zhí)行上下文中查找可處理引發(fā)的類型異常的 catch 子句,或查找可以處理任何類型的異常的 catch 處理程序。按照 catch 處理程序在 try 塊后面的顯示順序檢查這些處理程序。如果未找到適當(dāng)?shù)奶幚沓绦?,則檢查下一個動態(tài)封閉的 try 塊。此過程將繼續(xù),直到檢查最外面的封閉 try 塊。
如果仍未找到匹配的處理程序,或者在展開過程中但在處理程序獲得控制前發(fā)生異常,則調(diào)用預(yù)定義的運行時函數(shù) terminate。如果在引發(fā)異常后但在展開開始前發(fā)生異常,則調(diào)用 terminate。
如果找到匹配的 catch 處理程序,并且它通過值進行捕獲,則通過復(fù)制異常對象來初始化其形參。如果它通過引用進行捕獲,則初始化參數(shù)以引用異常對象。在初始化形參后,堆棧的展開過程將開始。這包括對與 catch 處理程序關(guān)聯(lián)的 try 塊的開頭和異常的引發(fā)站點之間完全構(gòu)造(但尚未析構(gòu))的所有自動對象的析構(gòu)。析構(gòu)按照與構(gòu)造相反的順序發(fā)生。執(zhí)行 catch 處理程序且程序會在最后一個處理程序之后(即,在不是 catch 處理程序的第一個語句或構(gòu)造處)恢復(fù)執(zhí)行??刂浦荒芡ㄟ^引發(fā)的異常進入 catch 處理程序,而絕不會通過 goto 語句或 switch 語句中的 case 標(biāo)簽進入。
堆棧展開示例
以下示例演示引發(fā)異常時如何展開堆棧。線程執(zhí)行將從 C 中的 throw 語句跳轉(zhuǎn)到 main 中的 catch 語句,并在此過程中展開每個函數(shù)。請注意創(chuàng)建 Dummy 對象的順序,并且會在它們超出范圍時將其銷毀。還請注意,除了包含 catch 語句的 main 之外,其他函數(shù)均未完成。函數(shù) A 絕不會從其對 B() 的調(diào)用返回,并且 B 絕不會從其對 C() 的調(diào)用返回。如果取消注釋 Dummy 指針和相應(yīng)的 delete 語句的定義并運行程序,請注意絕不會刪除該指針。這說明了當(dāng)函數(shù)不提供異常保證時會發(fā)生的情況。有關(guān)詳細信息,請參閱“如何:針對異常進行設(shè)計”。如果注釋掉 catch 語句,則可以觀察當(dāng)程序因未經(jīng)處理的異常而終止時將發(fā)生的情況。

#include <string>
#include <iostream>
using namespace std;

class MyException{};
class Dummy
{
 public:
 Dummy(string s) : MyName(s) { PrintMsg("Created Dummy:"); }
 Dummy(const Dummy& other) : MyName(other.MyName){ PrintMsg("Copy created Dummy:"); }
 ~Dummy(){ PrintMsg("Destroyed Dummy:"); }
 void PrintMsg(string s) { cout << s << MyName << endl; }
 string MyName; 
 int level;
};


void C(Dummy d, int i)
{ 
 cout << "Entering FunctionC" << endl;
 d.MyName = " C";
 throw MyException(); 

 cout << "Exiting FunctionC" << endl;
}

void B(Dummy d, int i)
{
 cout << "Entering FunctionB" << endl;
 d.MyName = "B";
 C(d, i + 1); 
 cout << "Exiting FunctionB" << endl; 
}

void A(Dummy d, int i)
{ 
 cout << "Entering FunctionA" << endl;
 d.MyName = " A" ;
 // Dummy* pd = new Dummy("new Dummy"); //Not exception safe!!!
 B(d, i + 1);
 // delete pd; 
 cout << "Exiting FunctionA" << endl; 
}


int main()
{
 cout << "Entering main" << endl;
 try
 {
  Dummy d(" M");
  A(d,1);
 }
 catch (MyException& e)
 {
  cout << "Caught an exception of type: " << typeid(e).name() << endl;
 }

 cout << "Exiting main." << endl;
 char c;
 cin >> c;
}


輸出:
 Entering main
 Created Dummy: M
 Copy created Dummy: M
 Entering FunctionA
 Copy created Dummy: A
 Entering FunctionB
 Copy created Dummy: B
 Entering FunctionC
 Destroyed Dummy: C
 Destroyed Dummy: B
 Destroyed Dummy: A
 Destroyed Dummy: M
 Caught an exception of type: class MyException
 Exiting main.



異常規(guī)范 (throw)
異常規(guī)范是在 C++11 中棄用的 C++ 語言功能。這些規(guī)范原本用來提供有關(guān)可從函數(shù)引發(fā)哪些異常的摘要信息,但在實際應(yīng)用中發(fā)現(xiàn)這些規(guī)范存在問題。證明確實有一定用處的一個異常規(guī)范是 throw() 規(guī)范。例如:


void MyFunction(int i) throw();

告訴編譯器函數(shù)不引發(fā)任何異常。它相當(dāng)于使用 __declspec(nothrow)。這種用法是可選的。
(C++11) 在 ISO C++11 標(biāo)準(zhǔn)中,引入了 noexcept 運算符,該運算符在 Visual Studio 2015 及更高版本中受支持。盡可能使用 noexcept 指定函數(shù)是否可能會引發(fā)異常。
Visual C++ 中實現(xiàn)的異常規(guī)范與 ISO C++ 標(biāo)準(zhǔn)有所不同。下表總結(jié)了 Visual C++ 的異常規(guī)范實現(xiàn):

異常規(guī)范 含義
throw() 函數(shù)不會引發(fā)異常。但是,如果從標(biāo)記為 throw() 函數(shù)引發(fā)異常,Visual C++ 編譯器將不會調(diào)用意外處理函數(shù)。如果使用 throw() 標(biāo)記一個函數(shù),則 Visual C++ 編譯器假定該函數(shù)不會引發(fā) C++ 異常,并相應(yīng)地生成代碼。由于 C++ 編譯器可能會執(zhí)行代碼優(yōu)化(基于函數(shù)不會引發(fā)任何 C++ 異常的假設(shè)),因此,如果函數(shù)引發(fā)異常,則程序可能無法正確執(zhí)行。
throw(...) 函數(shù)可以引發(fā)異常。
throw(type) 函數(shù)可以引發(fā) type 類型的異常。但是,在 Visual C++ .NET 中,這被解釋為 throw(...)。

如果在應(yīng)用程序中使用異常處理,則一定有一個或多個函數(shù)處理引發(fā)的異常。在引發(fā)異常的函數(shù)和處理異常的函數(shù)間調(diào)用的所有函數(shù)必須能夠引發(fā)異常。
函數(shù)的引發(fā)行為基于以下因素:

  • 您是否在 C 或 C++ 下編譯函數(shù)。
  • 您所使用的 /EH 編譯器選項。
  • 是否顯式指定異常規(guī)范。

不允許對 C 函數(shù)使用顯式異常規(guī)范。

下表總結(jié)了函數(shù)的引發(fā)行為:

2016125173453469.png (697×254)

// exception_specification.cpp
// compile with: /EHs
#include <stdio.h>

void handler() {
 printf_s("in handler\n");
}

void f1(void) throw(int) {
 printf_s("About to throw 1\n");
 if (1)
  throw 1;
}

void f5(void) throw() {
 try {
  f1();
 }
 catch(...) {
  handler();
 }
}

// invalid, doesn't handle the int exception thrown from f1()
// void f3(void) throw() {
// f1();
// }

void __declspec(nothrow) f2(void) {
 try {
  f1();
 }
 catch(int) {
  handler();
 }
}

// only valid if compiled without /EHc 
// /EHc means assume extern "C" functions don't throw exceptions
extern "C" void f4(void);
void f4(void) {
 f1();
}

int main() {
 f2();

 try {
  f4();
 }
 catch(...) {
  printf_s("Caught exception from f4\n");
 }
 f5();
}

輸出:

About to throw 1
in handler
About to throw 1
Caught exception from f4
About to throw 1
in handler

相關(guān)文章

  • C語言實現(xiàn)倒置字符串的兩種方法分享

    C語言實現(xiàn)倒置字符串的兩種方法分享

    這篇文章主要和大家詳細介紹了利用C語言實現(xiàn)倒置字符串的兩種方法,文中的示例代碼講解詳細,感興趣的小伙伴可以跟隨小編一起動手嘗試一下
    2022-08-08
  • C語言實現(xiàn)YUV文件轉(zhuǎn)JPEG格式

    C語言實現(xiàn)YUV文件轉(zhuǎn)JPEG格式

    這篇文章主要為大家詳細介紹了如何利用C語言實現(xiàn)將YUV文件轉(zhuǎn)為JPEG格式,文中的示例代碼講解詳細,感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下
    2023-12-12
  • C語言實現(xiàn)三子棋小游戲全程詳解

    C語言實現(xiàn)三子棋小游戲全程詳解

    完成一個三子棋的代碼并不是很難,有困難且重要的是完成這個游戲代碼所具備的思想,因為思想上的進步才是真正的進步,當(dāng)我們有了這個思想上的武器,寫出別的代碼,難度就不會高
    2022-05-05
  • C語言模擬擲骰子游戲

    C語言模擬擲骰子游戲

    這篇文章介紹了C語言模擬擲骰子游戲的方法,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。需要的朋友可以收藏下
    2021-11-11
  • C語言實現(xiàn)乒乓球比賽

    C語言實現(xiàn)乒乓球比賽

    這篇文章主要為大家詳細介紹了C語言實現(xiàn)乒乓球比賽,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2020-05-05
  • C++實現(xiàn)小型復(fù)數(shù)計算器

    C++實現(xiàn)小型復(fù)數(shù)計算器

    這篇文章主要為大家詳細介紹了C++實現(xiàn)小型復(fù)數(shù)計算器,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2021-06-06
  • 詳解C語言中的字符串?dāng)?shù)組

    詳解C語言中的字符串?dāng)?shù)組

    這篇文章主要介紹了C語言中的字符串?dāng)?shù)組,本文通過示例代碼給大家介紹的非常詳細,具有一定的參考借鑒價值,需要的朋友可以參考下
    2019-09-09
  • 基于Qt播放器的實現(xiàn)詳解(支持Rgb,YUV格式)

    基于Qt播放器的實現(xiàn)詳解(支持Rgb,YUV格式)

    這篇文章主要為大家詳細介紹了如何利用Qt實現(xiàn)簡易的播放器,可以支持支持Rgb,YUV格式。文中的示例代碼講解詳細,感興趣的小伙伴可以嘗試一下
    2022-12-12
  • C語言數(shù)據(jù)結(jié)構(gòu)經(jīng)典10大排序算法刨析

    C語言數(shù)據(jù)結(jié)構(gòu)經(jīng)典10大排序算法刨析

    這篇文章主要介紹了C語言中常用的10種排序算法及代碼實現(xiàn),開發(fā)中排序的應(yīng)用需要熟練的掌握,因為是基礎(chǔ)內(nèi)容,那C語言有哪些排序算法呢?本文小編就來詳細說說,需要的朋友可以參考一下
    2022-02-02
  • 基于Sizeof與Strlen的區(qū)別以及聯(lián)系的使用詳解

    基于Sizeof與Strlen的區(qū)別以及聯(lián)系的使用詳解

    本篇文章是對Sizeof與Strlen的區(qū)別以及聯(lián)系的使用進行了詳細的介紹。需要的朋友參考下
    2013-05-05

最新評論