boost::swap是对标准库里的std::swap的增强和泛化,为交换两个变量的值提供便捷的方法。
为了使用需包含头文件: #include <boost/swap.hpp>
原理
c98标准中的std::swap():
template<typename T>
void swap(T& a,T& b)
{
T tmp(a);
a = b;
b = temp;
}
在标准库的swap中,要求交换的对象必须是可拷贝构造和可拷贝赋值的,效率低,需要进行一次复制构造和两次赋值操作。c++11标准使用转移语义对std::swap()进行优化:
template<typename T>
void swap(T& a,T& b)
{
T tmp = std::move(a); //把a'偷'到tmp
a = std::move(b); //把b'偷'到a
b = std::move(tmp); //把tmp'偷'到b
}
但不是所有的类都实现了自己的状态转移构造和赋值函数的,而且编译器的支持也是个必须考虑的问题,因此对于我们写的类,最好能够实现优化的swap()来提高效率。
解决方案有两种:一种是直接利用函数重载,编写同名的swap函数,调用函数的高校成员交换函数,不会使用标准库的swap,第二种是使用ADL(参数依赖查找)查找模板特化的std::swap()。
boost::查找有无针对类型T的std::swap()的特化或通过ADL查找模板特化的swap(),如果有则调用,查找失败则退化为std::swap();由于boost::swap() 和std::swap()同名,所以我们不能用using打开boost名字空间,应该用boost名字空间限定的方式调用它。
- 交换数组
boost::swap()可以直接交换两个数组的内容,但要求参与交换的两个数组必须是具有相同的长度。int al[10],a2[12]; //两个不通长度的数组 boost::swap(al,a2) //编译错误
特化的std::swap()--以简单的三维空间节点交换为例子,运用模板特化的方法使用boost::swap():
#include <boost/swap.hpp> #include <ostream> using namespace std; class point { int x,y,z; public: explict point(int a=0,int b=0,int c=0): x(a),y(b),z(c) {} void swap(point &p) { std::swap(x,p.x); std::swap(y,p.y); std::swap(z,p.z); cout<<"inner swap"<<endl } }; namespace std{ template<> void swap(point &x,point &y) { x.swap(y); } } int main() { point a(1,2,3),b(4,5,6); cout<<"std::swap"<<endl; std::swap(a,b); cout<<"boost::swap"<<endl; boost::swap(a,b); } //运行结果: std::swap inner swap boost::swap inner swap 由于我们在名字空间特化了std::swap,因此boost::swap和std::swap调用结果是相同的,都使用了特化后的swap函数。
特化ADL可找到的swap
唯一改动的是实现全局域的swap函数:#include <boost/swap.hpp> #include <ostream> using namespace std; class point { int x,y,z; public: explict point(int a=0,int b=0,int c=0): x(a),y(b),z(c) {} void swap(point &p) { std::swap(x,p.x); std::swap(y,p.y); std::swap(z,p.z); cout<<"inner swap"<<endl } }; void swap(point & x,point& y) { x.swap(y); } int main() { point a(1,2,3),b(4,5,6); cout<<"std::swap"<<endl; std::swap(a,b); cout<<"boost::swap"<<endl; boost::swap(a,b); } //运行结果: std::swap boost::swap inner swap 与之前的特化std::swap不同,std::swap使用了标准的交换操作,而boost::swap通过ADL规则找到全局名字空间的特化交换函数,实现高效的交换。