[转载]http://blog.csdn.net/u011058765/article/details/46663827
考虑写出一个不抛出异常的swap函数
本节讲解如何自定义一个高效的swap函数
对于std名空间中的swap缺省函数如下所示
namespace std{
template<typename T>
void swap(T& a, T& b)
{
T temp(a);
a=b;
b=temp;
}
}
class WidgetImpl{
public:
……
private:
int a,b,c; //数据很多,复制意味时间很长
std::vector<double> b;
……
};
我们可以看到,当交换对象的数据很大时,以上swap的执行效率会很慢,为了改变这种状况,作者提出以下方法;
重新定义一个类
class Widget{
public:
Widget(const Widget& rhs);
Widget& operator=(const Widget& rhs
{
…… //复制Widget时,复制WidgetImpl对象
*pImpl=*(ths.pImpl);
……
}
……
private:
WidgetImpl* pImpl;//指针,含有Widget的数据
};
如果置换两个Widget对象值,只需要置换其pImpl指针,那么效率就会很高。
那么怎样定义swap呢?
如下:
calss Widget{
public:
……
void swap(Widget& other)
{
using std::swap;//这个声明有必要
swap(pImpl, other.pImpl);
}
……
};
namespace std{
template<> //修订后的swap版本
void swap<Widget>(Widget& a, Widget& b)
{
a.swap(b); //调用其成员函数
}
}
Widget w1,w2;
swap(w1,w2);//调用名空间的全特化Widget版本的swap.
从上面的代码我们可以看出完成了我们的目的,实现两个WidgetImpl对象交换,只交换他们的指针。当然这里需要构造出一个交换类Widget,需要全特化Widget 类型的swap,需要在函数体内定义member函数swap。
那么,读者就迷茫了,绕了一大圈,怎么不直接调用成员函数swap,这是因为当你用swap(a,b)语句时,它会拥有自动合适匹配的功能。更适合客户使用,实现接口的一致性和简易性。比如说:客户可以直接使用swap(w1,w2),而不是w1.swap(w2)。
下面我们来介绍当两个类都是template,如何解决上面的问题?
如下:
template<typename T>
class WidgetImpl{……};
template<typename T>
class Widget{……};
我们可以重新命名一个名空间如下:
namespace WidgetStuff{
……//模板化的WidgetImpl等
template<typename T>//内含swap函数
class Widget{……};
……
template<typename T>
void swap(Widget<T>& a,//non-member,不属于std命名空间
Widget<T>& b)
{
a.swap(b);
}
}
Widget<int> w1,w2;
swap(w1,w2);//调用名空间WidgetStuff的Widget<int>版本的swap.