近日在研究share ptr的源码,第一遍看的时候对于里面的swap函数不以为然,反复再三之后才知到其中奥妙,于是,在这里,我来谈谈swap函数的理解,为接下来的share ptr的源码分析做铺垫。
swap是异常安全编程的脊柱,以及用来处理自我赋值可能性的一个常用机制。
首先,咱们来看看典型的swap实现:
namespace std{
template<typename T>
void swap(T &a,T &b){
T temp(a);
a=b;
b=temp;
}
我们想要交换两个对象,经典实现就是,我再造一个一模一样的临时对象,然后你们开始交换,交换完以后,我把临时对象的内存释放。当然这段代码真的是一点亮点都没有,而且,大部分也都是用这个方法,并且绝对是安全的,但是,我们想想,倘若我们有一种类型, 是用一个指针指向一个对象,内部含有真正的数据。对于这种类型,我们想要交换两个对象的值,就可以把复杂度降到最低:我们只需要交换两个指针就可以了,这就是大名鼎鼎的pimpl手法,也是桥接模式的一个变种,对于这种手法,我就举一个最简单的例子:
class myimpl{
public:
...
private:
int x,y,z;
std::queue<int> que;
sta::stack<int> sta;
};
class my{
public:
...
private:
myimpl *impl;
};
看第二个类,第二个类的private里面就只有一个指向第一个类的指针。我们想要交换,就只需要交换指针就可以了。
再回顾一下我之前实现的smartptr类,里面也是有指针,然而怎么才能告诉编译器我要交换指针。
这里要引入一个偏特化的概念,我们把swap偏特化,写一个特定的swap就可以了:
void swap(myimpl &p1)
{
using std::swap;
swap(impl,p1.impl);
}
我们在swap里面using声明swap,这样就可以由编译器选择最合适的版本,交换指针,当然这是异常安全的版本。