为了异常安全(swap,share_ptr)——Effecive C++
互斥锁:
假设我们要在多线程中实现背景图片的控制:
class PrettyMenu{
public:
……
void changeBackground(std::istream& imgSrc);//改变背景图片
……
private:
Mutex mutex; //互斥量
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就不会被执行,会被一直锁住
- 发生上面异常,imageChanges也被累加,但实际上新的图片没有被安装
对于第一个问题:
被及时释放的互斥锁:
share_ptr我们可以指定它的删除器,所以可以在删除器中释放互斥锁.
如此即使是发生了异常,互斥锁也能够被及时的释放。
class Lock{
public:
explicit Lock(Mutex* mu):mutexPtr(mu,unlock)//以某个Mutex初始化,unlock作为删除其
{
lock(mutexPtr);
}
private:
shared_prt<Mutex> mutexPtr;
};
如果通过一个Lock类,然后在析构函数阶段进行 unlock也可以避免这个问题。但是这样的类进行复制的时候
可能存在很多不合理的问题。
如果希望保存资源直到最后一个对象消失,并且在复制的时候是引用计数,可以使用上面这种情况。
对于第二个问题:
swap的 全or无:
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;//**条款**25
Lock m1(&mutex);
std::tr1::shared_ptr<PMImpl> pNew(new PMImpl(*pImpl));
pNew->bgImage.reset(new Image(imgSrc));;//修改副本
++pNew->imageChanges;
swap(pImpl,pNew);
}
我们可以先弄一个副本,在进行完所有的操作之后,再与目标对象进行交换。
从而实现: 要不然就不处理,不然就全部处理完。
所以我们需要一个 不会抛出异常的swap操作。
参考:
《Effective C++》
为了异常安全(swap,share_ptr)——Effecive C++的更多相关文章
- 【25】考虑写出一个不抛异常的swap函数
1.swap交换对象值,std提供了实现方法模版的实现,它的实现是交换对象值. namespace std { template<typename T> void swap(T& ...
- [Effective C++ --025]考虑写出一个不抛异常的swap函数
引言 在我的上一篇博客中,讲述了swap函数. 原本swap只是STL的一部分,而后成为异常安全性编程的脊柱,以及用来处理自我赋值可能性. 一.swap函数 标准库的swap函数如下: namespa ...
- EC读书笔记系列之13:条款25 考虑写出一个不抛异常的swap函数
记住: ★当std::swap对你的类型效率不高时,提供一个swap成员函数,并确定其不抛出异常 ★若你提供一个member swap,也该提供一个non-member swap来调用前者.对于cla ...
- Effective C++:条款25:考虑写出一个不抛异常的swap函数
(一) 缺省情况下swap动作可由标准程序库提供的swap算法完毕: namespace std { template<typename T> void swap(T& a, T& ...
- 考虑实现一个不抛异常的swap
Effective C++:参考自harttle land 类的swap实现与STL容器是一致的:提供swap成员函数, 并特化std::swap来调用那个成员函数. class Widget { p ...
- Effective C++ -----条款25:考虑写出一个不抛异常的swap函数
当std::swap对你的类型效率不高时,提供一个swap成员函数,并确定这个函数不抛出异常. 如果你提供一个member swap,也该提供一个non-member swap用来调用前者.对于cla ...
- 《Effective C++》item25:考虑写出一个不抛异常的swap函数
std::swap()是个很有用的函数,它可以用来交换两个变量的值,包括用户自定义的类型,只要类型支持copying操作,尤其是在STL中使用的很多,例如: int main(int argc, _T ...
- Effective C++ Item 25 考虑写出一个不抛异常的swap函数
本文为senlie原创,转载请保留此地址:http://blog.csdn.net/zhengsenlie 经验:当std::swap对你的类型效率不高时,提供一个swap成员函数,并确定这个函数不抛 ...
- 不抛异常的swap函数
namespace AStuff{ template<typename T> class A { public: void swap(A *other) { using std::swap ...
随机推荐
- C语言第一次博客作业---顺序机构基础练习
一.PTA实验作业 题目1.温度转换 本题要求编写程序,计算华氏温度150°F对应的摄氏温度.计算公式:C=5×(F−32)/9,式中:C表示摄氏温度,F表示华氏温度,输出数据要求为整型. 1.实验代 ...
- js计时功能
//个位秒加 function time4jia() { //分钟60为上限 所有加停止 if (sz(a('time1').innerHTML) == 6) { return; } var m4 = ...
- 单向链表在O(1)时间内删除一个节点
说删链表节点,第一时间想到就是遍历整个链表,找到删除节点的前驱,改变节点指向,删除节点,但是,这样删除单链表的某一节点,时间复杂度就是O(n),不符合要求: 时间复杂度是O(n)的做法就不说了,看看O ...
- Twisted UDP编程技术
实战演练1:普通UDP UDP是一种无连接对等通信协议,没有服务器和客户端概念,通信的任何一方均可通过通信原语直接和其他方通信 1.相对于TCP,UDP编程只需定义DatagramProtocol子类 ...
- bzoj千题计划271:bzoj4869: [六省联考2017]相逢是问候
http://www.lydsy.com/JudgeOnline/problem.php?id=4869 欧拉降幂+线段树,每个数最多降log次,模数就会降为1 #include<cmath&g ...
- Codechef March Challenge 2014——The Street
The Street Problem Code: STREETTA https://www.codechef.com/problems/STREETTA Submit Tweet All submis ...
- 数据结构与算法 —— 链表linked list(01)
链表(维基百科) 链表(Linked list)是一种常见的基础数据结构,是一种线性表,但是并不会按线性的顺序存储数据,而是在每一个节点里存到下一个节点的指针(Pointer).由于不必须按顺序存储, ...
- JAVA_SE基础——14.循环结构语句
建议有些基础的同学阅读,0基础可能会有些困难(最好看正文配合基础课本的例子) 所谓循环语句主要就是在满足条件的情况下反复执行某一个操作.Java提供了3种常用的循环语句,分别为for循环语句.whil ...
- 求解数独难题, Sudoku问题(回溯)
Introduction : 标准的数独游戏是在一个 9 X 9 的棋盘上填写 1 – 9 这 9 个数字,规则是这样的: 棋盘分成上图所示的 9 个区域(不同颜色做背景标出,每个区域是 3 X 3 ...
- Appium+python测试app实例
Appium和selenium差不到,只是一个用于测web,一个用于测APP.下面记录一下我搭的测试框架,同样是基于PO模式,用的unittest. 最后测试报告如下: 1.1 代码结构 这 ...