C++異常處理與臨時副本
首先以一個簡單的程式開頭如下:
#include
using namespace std;
void test(int& a,int& b)
{
int c;
if(a==b)
{
cout<<"now a==b!"<<endl;
throw a;
cout<<"test p is :"<<&a<<endl;
cout<<"this whill not process!!"<<endl;
}
else
{
c=a+b;
cout<<a<<"<>"<<b<<endl;
cout<<"a+b="<<c<<endl;
}
}
int main(void)
{
for(int a=0,b=10;a<10;a++,b--)
{
cout<<"main p is: "<<&a<<endl;
try
{
test(a,b);
}
catch(int& a)
{
cout<<"catch program hint!!"<<endl;
cout<<"catch p is"<<&a<<endl;
continue;
}
}
}
主要是3個關鍵字
try{} --用於指定異常可能被啟用打程式碼塊
catch{} --異常處理程式
throw{} --類似於執行返回語句,類似return,後面的語句將不執行,但是和return不同是
他是返回到一個型別匹配的catch處理語句,如果有多個匹配的catch處理語句,則
按照順序第一個catch語句生效。
比如:
#include
using namespace std;
void test(int& a,string& b);
void testb(string& b);
void testa(int& a);
int main(void)
{
int a;
string b;
cin>>a;
cin>>b;
cout<<&a<<endl;
cout<<&b<<endl;
try
{
test(a,b);
}
catch(int& a)
{
cout<<"2th catch a values:"<<a<<" a's="" pionter="" is="" :"<<&a<<endl; return 1;
}
catch(string& b)
{
b="test1";
cout<<b<<endl;
cout<<&b<<endl;
return 2;
}
return 0;
}
void test(int& a,string& b)
{
if(a>0)
{
try
{
testa(a);
testb(b);
}
catch(int& a)
{
cout<<"1th catch a values:"<<a<<endl;
a=a+1;
cout<<"test:"<<&a<<endl;
throw a;
}
}
cout<<"test() int: "<<a<<" string:="" "<<b<<endl; }
void testa(int& a)
{
if(a==1)
{
a=a+1;
cout<<"testa:"<<&a<<endl;
throw a;
}
}
void testb(string& b)
{
if(b=="test")
{
throw b;
}
}
這種情況下如果testb 中 b=="test"將觸發異常,但是throw b和test中catch(int& a)並不匹配,他會直接找到上層main中的
catch(string& b)
異常處理程式
但是testa 中a==1觸發異常,它會首先觸發test中的catch(int& a)異常處理程式因為型別匹配,然後throw到上層main中的異常
處理程式catch(int& a)
來看一下這個程式的輸出:
1
test
0x7ffd45151eac
0x7ffd45151eb0
testa:0x7ffd45151eac
1th catch a values:2
test:0x1c960f0
2th catch a values:3 a's pionter is :0x1c96180
這一次輸入為1 test 顯然是先進行了a++然後呼叫了testa函式同時返回異常到test中輸出為 1th catch a values:2,然後a++,然後後面的語句就不執行了
也就是testb(b)和cout<<"test() int: "<<a<<" string:="" "<<b<<endl;不會執行,因為testa中的throw直接到了catch塊,然後catch 中同樣執行了throw到了main函式的catch塊catch(int& a),到了
catch(int& a)
{
cout<<"2th catch a values:"<<a<<" a's="" pionter="" is="" :"<<&a<<endl; return 1;
}
輸出了為2th catch a values:3 a's pionter is :0x1c96180
我們這裡清楚看到在測試函式中,我使用的都是&a引用,但是在throw的時候卻傳遞全部是都是副本,本來a的地址為0x7ffd45151eac然後傳入到testa這個觸發函式中,
函式throw a返回的實際上是一個副本給了test 中的處理函式catch,這時候a的地址為0x1c960f0,然後再次test throw a同樣返回的是一個副本給了main函式中的catch地址為
0x1c96180,可見雖然我用的是引用但是throw返回確實是副本而不是一般理解的址傳遞,但是這裡引用的特性的沒有丟失也就是如果是基類地址任然可以
指向基類地址或者繼承類地址。
這裡要注意既然測試函式中throw的是副本,那麼我的test中a=a+1實際上已經不是更改原有的a的值的因為原有的a的地址是0x7ffd45151eac,然而
test中a的地址是0x1c960f0,這次a=a+1並沒有改變原有main中a的地址,如下:
稍稍修改一下
29 catch(int& a)
30 {
31
32 cout<<"2th catch a values:"<<a<<endl;
33 }
34 catch(string& b)
35 {
36
37 b="test1";
38 cout<<b<<endl;
39 }
40 cout<<"main a values:"<<a<<endl;
41 return 0;
42 }
讓程式異常處理後繼續執行,我們看到main中a的值還是2並不是3,原因就在於剛才說的,throw傳遞的是一個副本並不是原有的值,但是第一次傳遞給
testa的時候任然是傳入的地址所以a相當於只修改了一次並非兩次。
輸出如下:
1th catch a values:2
2th catch a values:3
main a values:2
</a<<endl;
</b<<endl;
</a<<endl;
</a<</a<</endl;
</a<</endl;
</a<<endl;
</endl;
</b<<endl;
</a<</endl;
</endl;
</endl;
</endl;
</endl;
</c<<endl;
</b<<endl;
</a<<"<></endl;
</endl;
</endl;
#include
using namespace std;
void test(int& a,int& b)
{
int c;
if(a==b)
{
cout<<"now a==b!"<<endl;
throw a;
cout<<"test p is :"<<&a<<endl;
cout<<"this whill not process!!"<<endl;
}
else
{
c=a+b;
cout<<a<<"<>"<<b<<endl;
cout<<"a+b="<<c<<endl;
}
}
int main(void)
{
for(int a=0,b=10;a<10;a++,b--)
{
cout<<"main p is: "<<&a<<endl;
try
{
test(a,b);
}
catch(int& a)
{
cout<<"catch program hint!!"<<endl;
cout<<"catch p is"<<&a<<endl;
continue;
}
}
}
主要是3個關鍵字
try{} --用於指定異常可能被啟用打程式碼塊
catch{} --異常處理程式
throw{} --類似於執行返回語句,類似return,後面的語句將不執行,但是和return不同是
他是返回到一個型別匹配的catch處理語句,如果有多個匹配的catch處理語句,則
按照順序第一個catch語句生效。
比如:
#include
using namespace std;
void test(int& a,string& b);
void testb(string& b);
void testa(int& a);
int main(void)
{
int a;
string b;
cin>>a;
cin>>b;
cout<<&a<<endl;
cout<<&b<<endl;
try
{
test(a,b);
}
catch(int& a)
{
cout<<"2th catch a values:"<<a<<" a's="" pionter="" is="" :"<<&a<<endl; return 1;
}
catch(string& b)
{
b="test1";
cout<<b<<endl;
cout<<&b<<endl;
return 2;
}
return 0;
}
void test(int& a,string& b)
{
if(a>0)
{
try
{
testa(a);
testb(b);
}
catch(int& a)
{
cout<<"1th catch a values:"<<a<<endl;
a=a+1;
cout<<"test:"<<&a<<endl;
throw a;
}
}
cout<<"test() int: "<<a<<" string:="" "<<b<<endl; }
void testa(int& a)
{
if(a==1)
{
a=a+1;
cout<<"testa:"<<&a<<endl;
throw a;
}
}
void testb(string& b)
{
if(b=="test")
{
throw b;
}
}
這種情況下如果testb 中 b=="test"將觸發異常,但是throw b和test中catch(int& a)並不匹配,他會直接找到上層main中的
catch(string& b)
異常處理程式
但是testa 中a==1觸發異常,它會首先觸發test中的catch(int& a)異常處理程式因為型別匹配,然後throw到上層main中的異常
處理程式catch(int& a)
來看一下這個程式的輸出:
1
test
0x7ffd45151eac
0x7ffd45151eb0
testa:0x7ffd45151eac
1th catch a values:2
test:0x1c960f0
2th catch a values:3 a's pionter is :0x1c96180
這一次輸入為1 test 顯然是先進行了a++然後呼叫了testa函式同時返回異常到test中輸出為 1th catch a values:2,然後a++,然後後面的語句就不執行了
也就是testb(b)和cout<<"test() int: "<<a<<" string:="" "<<b<<endl;不會執行,因為testa中的throw直接到了catch塊,然後catch 中同樣執行了throw到了main函式的catch塊catch(int& a),到了
catch(int& a)
{
cout<<"2th catch a values:"<<a<<" a's="" pionter="" is="" :"<<&a<<endl; return 1;
}
輸出了為2th catch a values:3 a's pionter is :0x1c96180
我們這裡清楚看到在測試函式中,我使用的都是&a引用,但是在throw的時候卻傳遞全部是都是副本,本來a的地址為0x7ffd45151eac然後傳入到testa這個觸發函式中,
函式throw a返回的實際上是一個副本給了test 中的處理函式catch,這時候a的地址為0x1c960f0,然後再次test throw a同樣返回的是一個副本給了main函式中的catch地址為
0x1c96180,可見雖然我用的是引用但是throw返回確實是副本而不是一般理解的址傳遞,但是這裡引用的特性的沒有丟失也就是如果是基類地址任然可以
指向基類地址或者繼承類地址。
這裡要注意既然測試函式中throw的是副本,那麼我的test中a=a+1實際上已經不是更改原有的a的值的因為原有的a的地址是0x7ffd45151eac,然而
test中a的地址是0x1c960f0,這次a=a+1並沒有改變原有main中a的地址,如下:
稍稍修改一下
29 catch(int& a)
30 {
31
32 cout<<"2th catch a values:"<<a<<endl;
33 }
34 catch(string& b)
35 {
36
37 b="test1";
38 cout<<b<<endl;
39 }
40 cout<<"main a values:"<<a<<endl;
41 return 0;
42 }
讓程式異常處理後繼續執行,我們看到main中a的值還是2並不是3,原因就在於剛才說的,throw傳遞的是一個副本並不是原有的值,但是第一次傳遞給
testa的時候任然是傳入的地址所以a相當於只修改了一次並非兩次。
輸出如下:
1th catch a values:2
2th catch a values:3
main a values:2
</b<<endl;
</a<<endl;
</a<</a<</endl;
</a<</endl;
</a<<endl;
</endl;
</b<<endl;
</a<</endl;
</endl;
</endl;
</endl;
</endl;
</c<<endl;
</b<<endl;
</a<<"<></endl;
</endl;
</endl;
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/7728585/viewspace-2123098/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- windows核心程式設計---未處理異常,向量化異常處理與C++異常Windows程式設計C++
- C++ 異常處理C++
- C++異常處理C++
- c++異常處理格式C++
- c++ 異常處理(2)C++
- c++ 異常處理(1)C++
- c++異常處理 (轉)C++
- C與C++中的異常處理 (轉)C++
- 異常處理與異常函式函式
- C++異常處理機制C++
- 【C++】 C++異常捕捉和處理C++
- C與C++中的異常處理11 (轉)C++
- C與C++中的異常處理13 (轉)C++
- C與C++中的異常處理12 (轉)C++
- C與C++中的異常處理14 (轉)C++
- C與C++中的異常處理15 (轉)C++
- C與C++中的異常處理16 (轉)C++
- C與C++中的異常處理17 (轉)C++
- C與C++中的異常處理3 (轉)C++
- C與C++中的異常處理4 (轉)C++
- C與C++中的異常處理5 (轉)C++
- C與C++中的異常處理7 (轉)C++
- C與C++中的異常處理6 (轉)C++
- C與C++中的異常處理9 (轉)C++
- C與C++中的異常處理8 (轉)C++
- C與C++中的異常處理10 (轉)C++
- Java 異常表與異常處理原理Java
- C++ 異常處理機制詳解:輕鬆掌握異常處理技巧C++
- 異常處理機制(二)之異常處理與捕獲
- C++錯誤和異常處理C++
- C++整理19_異常處理C++
- 強制型別轉換時的異常處理_java與c++比較型別JavaC++
- 異常篇——異常處理
- Linux 下 C++ 異常處理技巧LinuxC++
- C++和結構化異常處理C++
- 異常處理
- 異常處理與推導式
- C/C++學習筆記八(斷言與異常處理)C++筆記