swap函数,原本只是STL的一部分,后来成为异常安全性编程的脊柱,以及用来处理自我赋值可能性的一个常见机制。
典型实现:
namespace std {
template<typename T>
void swap(T& a, T& b)
{
T temp(a);
a = b;
b = temp;
}
};
如指针指向一个对象,内含真正数据,这种设计常见表现形式就是所谓的“pImpl”手法。一旦要置换两个对象值,唯一需要做的就是置换其pImpl指针,但缺省swap算法不知这点。
这里,可以针对对象特化,如:
Class Widget {
public:
...
void swap(Widget& other)
{
using std::swap;
swap(pImpl, other.pImpl); //置换的是pImpl指针
}
};
namespace std {
template<> // std::swap的一个全特化
void swap<Widget>(Widget& a, Widget& b)
{
a.swap(b);
}
};
写在最后
- 如果swap的缺省实现对你的class或class template提供可接受的效率,你不需要额外做任何事。任何尝试swap对象都会取得缺省版本
- 如果swap缺省版本的效率不足:
- 提供一个public swap成员函数,让它高效地swap你的类型的两个对象值。(绝不该抛异常)
- 在class或template所在的命名空间内提供一个非成员函数swap,并令它调用上述swap成员函数
- 如编写一个class(而不是class template),为你的class特化std::swap。并令它调用swap成员函数。
- 如果你调用swap,请确定包含一个using声明式,以便让std::swap在函数内可见,然后不加任何namespace修饰,直接调用swap。