C++异常处理与临时副本

简介: 首先以一个简单的程序开头如下: #include using namespace std; void test(int& a,int& b) {         int c;         if(a==b)         {            ...
首先以一个简单的程序开头如下:
#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;
相关文章
|
4月前
|
C++
C++ 语言异常处理实战:在编程潮流中坚守稳定,开启代码可靠之旅
【8月更文挑战第22天】C++的异常处理机制是确保程序稳定的关键特性。它允许程序在遇到错误时优雅地响应而非直接崩溃。通过`throw`抛出异常,并用`catch`捕获处理,可使程序控制流跳转至错误处理代码。例如,在进行除法运算或文件读取时,若发生除数为零或文件无法打开等错误,则可通过抛出异常并在调用处捕获来妥善处理这些情况。恰当使用异常处理能显著提升程序的健壮性和维护性。
78 2
|
7月前
|
安全 编译器 程序员
【C++ 泛型编程 进阶篇】 C++ 泛型编程 模板与异常处理、模板与友元之间的使用(一)
【C++ 泛型编程 进阶篇】 C++ 泛型编程 模板与异常处理、模板与友元之间的使用
100 1
|
7月前
|
安全 C++
C++中的异常处理与错误处理机制
C++中的异常处理与错误处理机制
86 0
|
6月前
|
C++
C++一分钟之—异常处理try-catch
【6月更文挑战第22天】C++异常处理机制,借助`try`、`catch`、`throw`管理错误,优雅处理异常,防止程序崩溃。`try`包围可能出错的代码,`catch`捕获异常,`throw`引发异常。基本结构是:`try-catch`块中,未捕获的异常将向上抛出。多`catch`块可按顺序捕获不同类型的异常。易错点包括忽视异常传播、不精确的`catch`和资源未清理。通过精确捕获、RAII技术和适当的异常策略,提升代码健壮性和效率。
49 1
|
6月前
|
C++
C++核心技术要点《异常处理详解》
C++核心技术要点《try-throw-catch异常处理详解》
52 2
|
6月前
|
程序员 编译器 C++
探索C++语言宝库:解锁基础知识与实用技能(类型变量+条件循环+函数模块+OOP+异常处理)
探索C++语言宝库:解锁基础知识与实用技能(类型变量+条件循环+函数模块+OOP+异常处理)
48 0
|
7月前
|
程序员 编译器 C++
C++中的异常处理:技术详解与实践
C++中的异常处理:技术详解与实践
120 1
|
7月前
|
C++
C++程序异常处理
C++程序异常处理
46 1
|
6月前
|
C++
C++对C的改进和拓展\异常处理
C++对C的改进和拓展\异常处理
39 0
|
6月前
|
C++
Essential C++ 第7章 异常处理
Essential C++ 第7章 异常处理