首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 开发语言 > C++ >

C++ 错误!

2012-10-19 
C++ 异常!!!学习自《More Effective C学习 》和《Effective C学习 》。1、永远不会回到抛出异常的地方。2、C规范要

C++ 异常!!!

学习自《More Effective C++学习 》和《Effective C++学习 》。


1、永远不会回到抛出异常的地方。

2、C++规范要求被做为异常抛出的对象必须被复制。不论通过传值捕获异常还是通过引用捕获(不能通过指针捕获这个异常,因为类型不匹配)都将进行拷贝操作。因为throw之后就离开了生存空间。

     一个被异常抛出的对象总是一个临时对象。

      catch的都是副本。

3、当异常对象被拷贝时,拷贝操作是由对象的拷贝构造函数完成的。该拷贝构造函数是对象的静态类型(static type)所对应类的拷贝构造函数,而不是对象的动态类型(dynamic type)对应类的拷贝构造函数。

4、在函数调用中不允许转递一个临时对象到一个非const引用类型的参数里(参见条款M19),但是在异常中却被允许。

5、catch (Widget w)...                // 通过传值捕获

                  ------------ catch时也会有一次拷贝过程。

                  ------------ 如果throw子类,catch基类,则此次拷贝也会导致截断情况。

6、catch进行异常匹配:

                1)一个用来捕获基类的catch子句也可以处理派生类类型的异常;

                               因此,先catch派生类的异常,再catch基类的异常!

                2)第二种是允许从一个类型化指针(typed pointer)转变成无类型指针;                     

                               catch (const void*)...                 //捕获任何指针类型异常

                3)如果是虚函数,则匹配最佳的catch???

                4)不支持其他默认转换,包括int到doule类型的转换;

7、通过指针捕获异常也不符合C++语言本身的规范。

               因为不知道抛出的异常是“全局”的还是“静态”的异常,不确定是否需要删除。

8、四个标准的异常――bad_alloc(当operator new(参见条款M8)不能分配足够的内存时,被抛出),bad_cast(当dynamic_cast针对一个引用(reference)操作失败时,被抛出),bad_typeid(当dynamic_cast对空指针进行操作时,被抛出)和bad_exception(用于unexpected异常;参见条款M14)――都不是指向对象的指针,所以你必须通过值或引用来捕获它们。

9、通过值来捕获异常也有问题。 //如果throw子类,catch基类,则多出的一次拷贝会导致截断问题。

     只能使用引用捕获异常!!!

10、“异常规格”,即在函数后的throw(...)定义,很恐怖!!!

         1) 编译器无法完全检查;而执行时如果违反了“规格”,则抛出unexpected异常,导致程序终止!!!

         2) 太难防范了,建议不使用!!!

         3)“异常规格”不是说没有异常了,而是说如果出现不在规格内的异常将是严重错误。

11、为了使你的异常开销最小化,只要可能就尽量采用不支持异常的方法编译程序,把使用try块和异常规格限制在你确实需要它们的地方,并且只有在确为异常的情况下(exceptional)才抛出异常。

12、提供“异常安全保证”!!!目标:不泄露资源;不破坏数据;

         不泄露资源:使用智能指针,智能lock等技术。

         不破坏数据分三种:

                基本型;

                       失败,则数据保持在有效状态下,但状态未知。

                强烈型:

                       失败,则恢复原状。

                       1、往往通过copy-and-swap实现。使用std::swap或自写的swap,不能抛出异常。

                       2、但有时候没意义。因为其他函数的“异常安全保证”太低,这个函数这么高,性能受影响,意义不大。

                不抛异常型:throw()

13、析构函数应该扑捉任何异常,然后吞下它们或者结束程序。

         如果 客户想对异常做出处理,则提供普通的“成员函数”(而非析构函数),运行客户主动执行该操作。


14、如果使用了pimpl即pointer to implementation方法,则std::swap低效,可以考虑自己编写swap特例。

             如果编写swap函数:1)定义一个高效的swap成员函数;

                                                    2)在名字空间,定义一个非swap成员函数;实现调用前者。

                                                    两个函数内部使用标准std::swap实现。

            可以参考stl中使用方法。

                 


热点排行