3.异常

条款09:利用destruction避免泄露资源

这个条款讲的大致还是RAII,然后将到了auto_ptr指针。提到了防止编译器自动为类生成拷贝构造函数和拷贝运算符的方法。除了上本书提到的将函数声明为private,c++新增了= delete语句,来说明这个函数是无用的。

条款10:在construction内阻止资源泄露

看到这个条款的时候,我还在思考,构造函数中会有资源泄露吗?

我们现在以RAII的方式管理资源,也就是构建好的资源在范围之外会自动销毁。但是如果构造函数还没写好,析构函数是不会被调用的。

考虑这么一种情况,如果构造函数中给两个指针开辟空间,new了两次。但是内存不够。第二次new的时候返回了一个bad_alloc,那么第一个已经开辟好的指针是不是内存泄漏了?

如何放置或者是处理这种内存泄漏呢。

首先,我们可以用try catch模块,获取new的报错,然后处理。这是个不错的解决办法。

但是如果是常量指针呢,那么我们只能通过成员初始化列表来初始化const指针了。这时候如何处理内存泄漏的问题呢。

这就是这章要引出的东西,也是之后会提到的,使用智能指针。

条款11:禁止异常流出destruction函数

如果再执行析构函数的时候,抛出异常,那么析构函数肯定不能合理的执行完。可能会产生许多问题,所以要避免异常流出析构函数。要在析构函数里catch异常并且处理

条款12:了解“抛出一个exception”与“传递一个参数”或“调用一个虚函数”之间的差异

下面是函数声明和catch子句的语法

class Widget{...};

void f1(Widget w);
void f1(widget&w);
void f1(const Widget& w);
void f1(Widget* w);
void f1(const Widget* w)

catch (Widget w)
catch (Widget& w)
catch (const widget& w)
catch (Widget* w)
catch (const Widget* w)

首先从传参说起,传参数有3种方法,按值传输需要一次拷贝构造函数,引用和指针都不需要复制。所以用引用传参是一个很好的选择

而throw和return其实很像,向调用者传递一个东西。但是和return不同的是,返回值可以是引用。但是throw必定会调用一次拷贝构造函数生成一个中间变量。

这也就是说,如果以普通方式catch一个异常,会调用两次构造函数。以引用方式catch一个异常,也会调用一个拷贝构造函数。

传递参数和catch另一个不同点在于,catch只能接受父类到子类的类型转换。以及有型指针到无型指针的转换。比如 const void*可以捕获任何类型的指针

第三个不同在于,catch是顺序匹配的。

条款13:以by reference方式捕捉exception

有三种方式捕捉exception,指针,引用和值。

对于指针来说,返回来的很可能是loacl stack对象,之后会被销毁。并且很多标准不允许返回指针

对于值来说,容易造成切割问题。并且有两次复制

对于引用来说,只有一次复制。并且不会有切割问题。所以,最好用引用

条款14:明智运用 exception specifications

对于exception specifications要保持持平的观点。他们为抛出什么异常提供了卓越的说明,但是违法的下场也很惨。并且只做局部性检验。可能会违反调用函数的exception

条款15:了解异常处理的成本

这个条款说明,异常处理的成本是巨大的。当然,这是在90年代末期写的书,当时编译器还不是很支持,显示不是很清楚。

加了异常和try语言,程序通常会慢上一些。就算里面没有调用try,光编译exception,代码就会多上很多。

Last updated

Was this helpful?