More Effective C++ 条款11 禁止异常流出destructor之外

1. ”两种情况下destructor会被调用。第一种情况是当对象在正常情况下被销毁,也就是当它离开了它的生存空间或是被明确的删除;第二种情况是当对象被exception处理机制——也就是exception传播过程中的stack-unwinding(栈展开)机制——销毁。”

2. 当destructor被调用时,可能(也可能不)有一个exception正在作用之中,但我们无法再destructor中区分这些状态(现在有了区分的办法。1995年7月 IOS/ANSI C++ 标准委员会加入一个新函数: uncaught_exception。如果某个exception正在作用中而尚未被捕捉的话,它会返回true)。当destructor抛出一个异常的时候而不会被destructor捕捉的时候,它会传播到destructor的调用端,如果这个destructor本身是因他某个exception而被调用的,terminate函数便会被调用,它默认调用abort函数终止程序。

3. 对于2有一个解决办法可以防止destructor抛出的异常传出destructor之外,那就是将destructor函数体包在一个try块之中,而catch(...)语句什么也不做,示例代码如下:

1 ~A(){
2     try{
3         ...
4     }
5     catch(...){}
6 }
7 //......代表中间的代码被省略,...代表C++的元运算符

4. 除了2所示原因,让exception传出destructor之外还有一个坏处:如果destructor抛出exception而没有在当地捕捉,那个destructor就是执行不全,也就是说它没有完成它应该完成的事情。

5. 综上,有两个理由支持我们采取措施阻止exception传出destructor之外:第一,它可以避免terminate函数在exception传播过程中的栈展开(stacking-unwinding)机制中被调用;第二,它可以协助确保destructors完成其应该完成的所有事情。

时间: 2024-11-05 02:27:14

More Effective C++ 条款11 禁止异常流出destructor之外的相关文章

Effective C++ 条款11,12 在operator= 中处理“自我赋值” || 复制对象时不要忘记每一个成分

1.潜在的自我赋值     a[i] = a[j];     *px = *py; 当两个对象来自同一个继承体系时,他们甚至不需要声明为相同类型就可能造成别名. 现在担心的问题是:假如指向同一个对象,当其中一个对象被删,另一个也被删,这会造成不想要的结果. 该怎么办? 比如:   widget& widget:: operator+ (const widget& rhs) {    delete pd;    pd = new bitmap(*rhs.pb);    return *thi

Effective C++ 条款11

在operator=中处理"自我赋值" 什么是自我赋值,很明显.就是自己的值赋值给了自己.下面的代码就是自我赋值: class Widget { public: Widget& operator=(const Widget& rhs) { delete p; p=new int(ths.p); return *this; } int *p; }; Widget w1,w2; w1=w2; w1=w1;//自我赋值. 如上代码,自我赋值的时候会出现删除自身数据的操作,这样

Effective C++ (笔记) : 条款11 -- 条款17

条款11:在operator=中处理"自我赋值" 自我赋值有时候不是那么明显,在处理循环(a[i] = a[j]).指针(*px = *py)和参数传递(func(const Base &rb, const Derived *pd))的时候可能会发生. Widget::operator=(const Widget& rhs) { delete pb; pb = new Bitmap(*rhs.pb); return *this; } 这是一份不安全的实现版本,在自赋值的

effective C++ 读书笔记 条款11

条款11: 在operator= 中处理"自我赋值" 在实现operator=时考虑自我赋值是必要的就像 x=y .我们不知道变量x与y代表的值是否为同一个值(把x和y说成是一个指针更恰当一点). 例如以下 第一版: #include <iostream> using namespace std; class bitmap { public: bitmap() { cout<<"调用bitmap()无參构造函数"<<endl; }

Effective C++——条款10条,条款11和条款12(第2章)

条款10:    令operator=返回一个reference to *this Have assignment operators return a reference to *this 关于赋值,可以把它们写成连锁形式: int x, y, z; x = y = z = 15; // 赋值连锁形式 赋值采用右结合律,所以上述连锁赋值被解析为: x = (y = (z = 15)); 这里15先被赋值给z,然后其结果(更新后的z)再被赋值给y,然后其结果(更新后的y)再被赋值给x. 为了实现

Effective C++ 条款八 别让异常逃离析构函数

class DBConn //这个class用来管理DBConnction对象 { public:   //自己设计一个新的DBConn接口 方法3 void close() { db.close(); closed = true; }     ~DBConn() //确保数据库连接总是会被关闭 { //db.close();   if (!closed) { try { db.close(); } catch() { //制作运转记录,记下对close的调用失 } } } protected:

More Effective C++----(14)审慎使用异常规格(exception specifications)

Item M14:审慎使用异常规格(exception specifications) 毫无疑问,异常规格是一个引人注目的特性.它使得代码更容易理解,因为它明确地描述了一个函数可以抛出什么样的异常.但是它不只是一个有趣的注释.编译器在编译时有时能够检测到异常规格的不一致.而且如果一个函数抛出一个不在异常规格范围里的异常,系统在运行时能够检测出这个错误,然后一个特殊函数unexpected将被自动地调用.异常规格既可以做为一个指导性文档同时也是异常使用的强制约束机制,它好像有着很诱人的外表. 不过

More Effective C++ 条款35 让自己习惯于标准C++ 语言

(由于本书出版于1996年,因此当时的新特性现在来说可能已经习以为常,但现在重新了解反而会起到了解C++变迁的作用) 1. 1990年后C++的重要改变 1). 增加了新的语言特性:RTTI,namespaces,bool,关键词mutable和explicit,enums作为重载函数之自变量所引发的类型晋升转换,以及"在class 定义区内直接为整数型(intergral) const static class members设定初值"的能力. 2). 扩充了Templates的特性

条款11:在operator = 中处理&quot;自我赋值&quot;

条款11:在operator = 中处理"自我赋值" 1.潜在自我赋值 int i = 5; int *x = &i; int *y = &i; *x = *y; 继承类的 class Base{}; class Derived: public Base {}; void DoSomeThing(const Base& base, const Derived &derived) { base = derived; } Derived d; Base *b