博客的所有内容都是个人理解,难免有理解错误的地方,欢迎大家多多拍砖!
一直以来非常讨厌java中的异常处理机制,虽然号称自己写过不少c++的程序,但是对于c++中的异常处理知识确实一片空白,根据C++ primer中的学习,总结个人的几点理解。
1、异常处理机制是程序中相互独立的部分在出现问题时,进行通讯的一种手段,这样做的优点是将问题的检测和问题的处理隔离开来。
2、异常类似于将实参传递给函数的方式进行抛出和捕获。异常会被第一个匹配的catch模块捕获,而不是最精确匹配的模块,因此有层次结构的多级异常处理机制共存时,最特殊的异常一定要排在最前面。异常对象由编译器进行管理,保证每个可能处理该异常的catch模块都能访问的该异常。
3、捕获异常的catch模块的形参的静态类型决定catch中可以执行的动作,如果传递的异常是派生类型,而catch模块的参数时基类类型,将会把派生类型转换成基类类型,在catch处理模块中只能使用基类的成员。
4、catch的形参是引用类型,那么操纵的异常就是抛出异常的本身,这时就可以使用派生类特有的一些成员。这里的一点启示就是,对象本身是不具有多态的特性的,只有引用或指针才具有多态。因此如果想使用异常的多态特性,catch的形参使用引用类型。
5、异常是必须进行处理的一类问题,如果不进行处理将会导致程序终止。另外一点就是,在析构函数中不能抛出异常,如果有异常出现将同样导致程序的终止。因为在抛出异常的模块中,会对该模块的局部变量进行适当的释放,在释放的工程中就可能会调用到某些类的析构函数,如果在该过程中又抛出异常,就会导致程序终止,因此析构函数不允许抛出异常。
6、异常的重新抛出。异常经过某个处理模块处理之后可能需要交给再上一级进行处理,这样需要重新抛出该异常。如果catch模块的形参不是引用,那么该模块对异常所做的处理不会影响到上一级的处理,只有是引用时,对异常的修改才会进行散播。
7、catch(...)方法可以捕获所有的异常类型,可以用在不知道异常具体类型但是须有做一些处理的情况。
上边提到再抛出异常的模块中,会对该模块的局部变量进行适当的释放。其中,就有不能释放的变量,比如使用new动态分配的内存空间。为了保证能正确释放动态分配的内存可以使用auto_ptr来保存,动态分配空间的指针。
1、auto_ptr只能保存一个指向对象的指针,不能保存一个数组的指针。因为auto_ptr释放时,会调用delete这样只能释放数组第一个元素的内存空间,其他的空间不能释放,造成了内存泄露。
2、auto_ptr能保存任意类型的指针,auto_ptr的构造函数是explicit类型,所以不能使用类类型的隐式转换。
3、auto_ptr的复制和赋值是破坏性的操作,所谓破坏性就是指,例如a = b,原来的auto_ptr a释放掉以前指向的空间,a指向b指向的空间,b不指向任何空间。这跟一般的指针有较大的差别。
4、禁止将两个auto_ptr指向同一空间,如果发生这种情况按照auto_ptr的释放逻辑,将会产生同一空间被释放两次的情况。