条款9: 使用析构函数防止资源泄漏
下面代码会产生的问题:pa->processAdoption()可能抛出异常,导致delete不被执行
void processAdoption(istream& datasource)
{
while(datasource)
{
ALA* pa = readALA(datasource);
pa->processAdopation();
delete pa;
}
}
解决方案:
使用智能指针,保证析构函数会被执行.
条款10: 防止构造函数里的资源泄漏
1) C++只销毁构造完全的函数,构造完全的对象指它的构造函数被完全执行.如果构造函数抛出异常,析构函数不可能被执行到.
2) 应该把声明为指针的类成员替换成他们相应的auto_ptr对象,在抛出异常的时候构造函数可以避免资源泄漏.
条款11: 阻止异常传递到析构函数以外
1) 析构函数抛出异常会导致之后的代码无法执行,造成资源泄漏.
2) 析构函数抛出异常时可能是另外一个异常调用,导致terminate.
条款12: 理解抛出异常与传递参数或者调用虚函数之间的不同
区别:
1) 函数调用的时候,控制权最终返回给调用者.当抛出异常的时候,控制权不回返回给抛出者.异常对象总是要被拷贝,当以传值方式被捕获得时候,他们被拷贝两次.
2) 函数调用者和被调函数之间,异常抛出者和捕获者之间都存在类型匹配,而他们所遵循的类型匹配是不同的.
3) catch语句永远以他们所出现的顺序被执行.最先匹配.
1. C++要求对象必须以拷贝的形式抛出异常,即使被抛出的对象没有被销毁的危险,他还是要以拷贝的形式被抛出.
2. 当一个对象作为异常被拷贝的时候,这个拷贝是由该对象的拷贝构造函数来实施,这个拷贝构造函数是指对象的静态类型而不是动态类型所对应的那个构造函数.拷贝永远是基于对象的静态类型.
catch (Widget& w)
{
...
throw;
}
catch (Widget& w)
{
...
throw w;
}
应该使用第一个,因为第二个类型总是Widget,因为w的静态类型是widget
第二个还会有效率问题
3. 两次拷贝问题
任何异常发生是都会产生临时拷贝.
catch (Widget w) // 2次拷贝
catch (Widget& w) // 1次拷贝
catch (const Widget& w) // 1次拷贝
条款13: 通过引用捕获异常
1) 通过值捕获异常的问题: 2次拷贝 可能会产生切割
2) 通过指针捕获异常的问题: 不知道时候需要delete 可能返回的是局部对象地址
3) 应该通过引用捕获异常