1、当std::swap对你的类型效率不高时,提供一个swap成员函数,并确定这个函数不抛出异常。
2、如果你提供一个member swap函数,也该提供一个non-member swap函数,后者用来调用前者。对于class(而非template),也请特化std::swap
3、调用swap时应针对std::swap使用using声明式,然后调用swap并且不带任何“命名空间资格修饰”。
4、为“用户定义类型”进行std template全特化是好的,但千万不要尝试在std内加入某些对std而言全新的东西。
如swap的缺省实现对你的class或者class template提供可接受的效率,你不需要额外做任何事情,任何尝试置换(swap)那种对象的人都会取得缺省版本,而那将有良好的运作。
其次,如果swap缺省实现版本的效率不足(那几乎总是以为你的class或者class template使用了某种pimpl【pointer 头implement】手法),尝试做以下 的事情:
1、提供一个public swap成员函数,让他高效的置换(swap)你的类型的两个对象值。
2、在你的class或者是template所在的命名空间内提供一个non-member swap函数,并令他调用上述swap函数(member swap函数)。
3、如果你正在编写一个class(而不是class template),为你的class特化std::swap。并令他调用你的swap成员函数。
最后,如果你调用swap函数,请确定包含一个using声明式,以便让std::swap在你的函数内曝光可见,然后不加任何namespace修饰符,赤裸裸的调用swap。
namespace std{
template<typename T>
void swap(T &a,T&b)
{
T temp(a);
a=b;
b=temp;
}
}
只要类型T支持copying(通过copy构造函数和copy assignment操作符完成)。
class AImpl{
public:
private:
int a,b,c;
std::vector<double> v; //可能有许多的数据,意味着copy的时间很长
}
class A{
public:
A(const A& rhs);
A& operator=(const A&rhs)
{
*pImpl = *(rhs.pImpl);
}
private:
AImpl *pImpl;
}
一旦要置换两个A对象,使用std::swap赋值的不仅仅是*pImpl对象,还有很多其他的对象,浪费。。。
特化版本:
namespace std{
template<>
void swap<A>(A &a, A&b)
{
swap(a.pImpl,b.pImpl);
}
}
”template<>“表示他是std::swap的一个全特化的版本。
class A{
public:
void swap(A *other)
{
using std::swap;
swap(pImpl,other.pImpl);
}
}
namespace std{
template<>
void swap<A>(A &a,A&b)
{
a.swap(b);
}
}
template<typename T>
class AImpl{...};
template<typename T>
class A{
........
};
name std{
template<typename T>
void swap<A<T>>( A<T>&a,A<T>&b) //错误,不合法
{
a.swap(b);
}
}
解决办法:
namespace AStuff{
template<typename T>
class A{....};
template<typename T>
void swap(A<T> &a,A<T>&b)
{
a.swap(b);
}
}
template<typename T>
void dosomething(T &a,T&b)
{
using std::swap;
swap(a,b);
}