(一)先看以下这些代码:
class PrettyMenu {
public:
void changeBackground(istream& imgSrc);
private:
Mutex mutex; //由于这个class希望用于多线程环境,所以它有这个相互排斥器作为并发控制之用
Image* bgImage; //眼下的背景图像
int imageChanges; //背景图像被改变的次数
}; void PrettyMenu::changeBackground(std::istream &imgSrc) {
lock(&mutex); //取得相互排斥器
delete bgImage; //摆脱旧的背景图像
++imageChanges; //改动图像变更次数
bgImage = new Image(imgSrc); //安装新的背景图像
unlock(&mutex); //释放相互排斥器
}
上面的函数不是“异常安全性”函数,由于“异常安全性”函数所需满足的两个条件。上面这个函数都不满足。
。
第一个条件:不泄露不论什么资源。
(上面这个函数当new Image(imgSrc)发生异常的话。unlock(&mutex)就永远不会被运行,所以就资源泄漏了)。
第二个条件:不同意数据败坏。(上面这个函数当new Image(imgSrc)发生异常的话,bgImage就是指向一个已删除的对象)。
(二)
(1)解决上面那个函数泄漏资源的问题的办法:用Lock class作为一种“确保相互排斥器被及时释放”的方法,以对象管理资源:
void PrettyMenu::changeBackground(std::istream &imgSrc) {
Lock m1(&mutex);
delete bgImage; //摆脱旧的背景图像
++imageChanges; //改动图像变更次数
bgImage = new Image(imgSrc); //安装新的背景图像
}
(2)解决上面那个函数数据败坏的办法:
首先,
异常安全函数提供下面三个保证之中的一个:
1. 基本承诺:假设异常被抛出,程序内的不论什么事物仍然保持在有效的状态下。
2. 强烈保证:假设异常被抛出,程序状态不改变。
3. 不抛掷保证:承诺绝不抛出异常,由于它们总是可以完毕它们原先承诺的功能。
又一次排列语句次序
class PrettyMenu {
...
std::tr1::shared_ptr<Image> bgImage;
...
}; void PrettyMenu::changeBackground(std::istream& imgSrc) {
Lock ml(&mutex);
bgImage.reset(new Image(imgSrc));
++imageChanges;
}
这两个改变差点儿足够让changeBackground提供强烈的异常安全保证。美中不足的是參数imgSrc。
假设Image构造函数抛出异常。有可能输入流的读取记号已被移走。而这种搬移对程序其余部分是一种可见的状态改变。
(三)
copy and swap的原则:为打算改动的对象做一个副本,在那个副本上做一切必要改动。若有不论什么改动动作抛出异常,源对象仍然保持未改变状态。待全部改变都成功后,再将改动过的副本和原对象在一个不抛出异常的swap中置换。
and swap方法下的pimpl idiom手段:
struct PMImpl {
std::tr1::shared_ptr<Image> bgImage;
int imageChanges;
};
class PrettyMenu {
private:
Mutex mutex;
std::tr1::shared_ptr<PMImpl> pImpl;
};
void PrettyMenu::changeBackground(std::istream& imgSrc) {
using std::swap;
Lock ml(&mutex);
std::tr1::shared_ptr<PMImpl> pNew(new PMImpl(*pImpl));
pNew->bgImage.reset(new Image(imgSrc)); //改动副本
++pNew->imageChanges;
swap(pImpl, pNew);//置换数据
}
请记住:
(1)异常安全函数(Exception-safe functions)即使发生异常也不会泄露资源或同意不论什么数据结构败坏。
这种函数区分为三种可能的保证:基本型、强烈型、不抛异常型。
(2)“强烈保证”往往可以以copy-and-swap实现出来,但“强烈保证”并不是对全部函数都可实现或具备现实意义。
(3)函数提供的“异常安全保证”通常最高仅仅等于其所调用的各个函数的“异常安全保证”中的最弱者。