C++异常深入剖析

C++异常机制由两部分组成,即抛出端处理端当程序抛出一个异常,控制权不会再回到抛出端

在抛出端,我们可以抛出一个数或对象,也可以抛出一个指针。

值得注意的是:被抛出的数、对象或指针都会产生一个副本,这个副本最后被传递给处理端。

完成抛出动作之后,原来的数、对象或指针会随之被销毁。

因此要保证此时指针所指向的内存区域不会被回收,否则,抛出的指针将指向一块无效内存区域。

另外,这个副本是对象的静态类型(不含有动态运行时特性)的拷贝构造函数创建出来的。

// 最后会在屏幕上打印出"A"
// 表明在抛出端产生对象副本时,调用的是A的拷贝构造函数
class A
{
public:
    A(){}
    A(const A& a)
    {
        printf("A\n");
    }
    ~A(){}
};

class B : public A
{
public:
    B(){}
    B(const B& a)
    {
        printf("B\n");
    }
    ~B(){}
};

void throwFunction()
{
    B b;
    A& a = b;
    throw a; // 此时会调用A的拷贝构造函数,而不是B的拷贝构造函数
}

int main(int argc, char* argv[])
{
    try{
        throwFunction();
    }
    catch(const A& e)
    {
        // ... ...
    }

    return 0;
}

++++++++++++++++++++++++++++++++++++++++++++

从以上我们得知,在throw XX时,会进行一次静态拷贝操作。

为了避免进行第二次拷贝,在处理端应使用引用接受被抛出来的对象,这个过程和函数参数传递类似。

如果程序没有处理异常,这该异常将由操作系统来接管,在Debug时,会弹出未处理的异常窗口,程序也因此中断运行。

需要注意的是,抛出端和处理端必须处于同一个模块内,异常才能被捕捉到。

例如:在try块中调用第三方dll的一个函数,并在其中发生了异常,那么catch块是捕捉不到该异常的。

关于处理端有五点值得注意:

(1) 对基本类型,不存在隐式转换

例如:throw出int类型的数时,catch(double a)捕捉块是捕捉不到该异常的。

(2) 在抛出对象时,对于多个catch块情况,应先将子类写在前,父类写在后

因为在匹配时,是从前往后匹配的。

(3) 当某一catch被匹配上

若在该catch块中直接throw,将导致该异常对象被重新抛出,此时不会进行拷贝。只是将该异常对象继续传递给下面的catch块

若在该catch块中throw XX,将会对XX对象进行静态拷贝。并将拷贝后的副本继续传递给下面的catch块。

(4) catch(const void* a)可以捕捉任何指针类型的异常

(5) catch(...)可以捕捉任何异常,如果需要用到这个catch块,确保该块放在末尾

class A
{
public:
    A(){}
    ~A(){}
};

class B : public A
{
public:
    B(){}
    ~B(){}
};

void throwFunction()
{
    B b;
    throw b;
}

int main(int argc, char* argv[])
{
    try{
        throwFunction();
    }
    catch(const B& e) // 子类写在父类前面
    {
        // ... ...
    }
    catch(const A& e)
    {
        // ... ...
    }
    catch(...)
    {
        // ... ...
    }

    return 0;
}

============================

Unwinding:现代编译器基本都支持unwinding功能,这使得在一个异常发生时,会将堆栈中的所有对象都析构掉,防止资源泄漏。

关于C++异常更多细节请参看:C++异常机制的实现方式和开销分析

原文链接: https://www.cnblogs.com/kekec/archive/2011/09/23/2186427.html

欢迎关注

微信关注下方公众号,第一时间获取干货硬货;公众号内回复【pdf】免费获取数百本计算机经典书籍

原创文章受到原创版权保护。转载请注明出处:https://www.ccppcoding.com/archives/32940

非原创文章文中已经注明原地址,如有侵权,联系删除

关注公众号【高性能架构探索】,第一时间获取最新文章

转载文章受原作者版权保护。转载请注明原作者出处!

(0)
上一篇 2023年2月8日 上午10:02
下一篇 2023年2月8日 上午10:07

相关推荐