boost swap

来源:互联网 发布:起点是网络出版社吗 编辑:程序博客网 时间:2024/04/28 16:41

swap:
 boost::swap是对标准库提供的std::swap的增强和泛华,为交换两个变量(可以是int等内置数据类型,或者是类实例,容器)的值提供了便捷的方法.
#include <boost/swap.hpp>
原理:
c++标准中的std::swap()
//std::swap的典型实现,具体代码依STL版本而不同
void swap(T& a, T& b)
{
 T tmp(a);
 a = b;
 b = tmp;
}
这里std::swap()要求交换的对象必须是可拷贝构造和可拷贝赋值的(即重载operator=),它提供的是最通用同时也是效率最低的方法,需要进行一次拷贝构造和两次赋值操作,所以对于我们自己写的类,最好能够实现优化的swap().
解决方案有两种:
 第一种方案是直接利用函数重载,编写一个同名的swap函数,这个swap()在调用类内部的高效成员交换函数,这样编译器在编译时就不会使用std::swap(),第二种方案是使用ADL(argument dependent lookup, 参数依赖查找,又称Koening Lookup)查找模板特化的swap,这两种方案就是boost::swap的工作原理:
 它查找有无针对类型T的std::swap()的特化swap()或者通过ADL查找模板特化的swap(),如果有则调用,如果两种查找都失败时,则退化为std::swap(),此外,boost::swap还增加了一个很实用的功能--对c++内建数组交换的支持.
boost::swap()函数的声明如下:
template<class T1, class T2>
void swap(T1& left, T2& right);

交换数组:
 交换两个数组的内容,它要求参与交换的两个数组必须具有相同的长度,下面是标准库算法fill_n将两个数组分别赋值为5和20,然后调用boost::swap()交换:
int a1[10];
int a2[10];
std::fill_n(a1, 10, 5); 
std::fill_n(a2, 10, 50);
boost::swap(a1, a2);//交换数组内容

boost::swap交换数组,使用了一个for循环,对数组中的每个元素调用单个元素版的boost::swap完成整个数组内容的交换。
注意:如果企图用boost::swap交换两个长度不相同的数组,那么将无法通过编译;

特化std::swap
 用模板特化的方法使用boost::swap.三维空间的点point作为例子,实现了内部高效的交换函数:
示例:
#include <iostream>
#include <boost/assign.hpp>
#include <boost/optional.hpp>
#include <boost/swap.hpp>
using namespace boost;
using namespace std;
class point
{
 int x, y, z;
public:
 explicit point(int a = 0, int b = 0, int c = 0):x(a), y(b), z(c){}
 void print() const
 { cout<< x << ","<< y << ","<< z<<endl;}
 void swap(point &p)
 {
  std::swap(x, p.x);
  std::swap(y, p.y);
  std::swap(z, p.z);
  cout << "inner swap" <<endl;
 }
};
//特化std::swap()的方法需要向std名字空间添加自定义函数
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);   //调用std::swap
 cout<<"boost::swap"<<endl;
 boost::swap(a, b);   //调用boost::swap
 system("pause");
 return 0;
}

 由于在名字空间特化了std::swap,因此,boost::swap与std::swap的效果相同都使用了特化后的swap函数.

特化ADL可找到的swap
 这次不变动std名字空间,而是在全局名字空间内实现swap函数:
示例:
#include <iostream>
#include <boost/assign.hpp>
#include <boost/optional.hpp>
#include <boost/swap.hpp>
using namespace boost;
using namespace std;
class point
{
 int x, y, z;
public:
 explicit point(int a = 0, int b = 0, int c = 0):x(a), y(b), z(c){}
 void print() const
 { cout<< x << ","<< y << ","<< z<<endl;}
 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);   //调用std::swap
 cout<<"boost::swap"<<endl;
 boost::swap(a, b);   //调用boost::swap
 system("pause");
 return 0;
}
 这段代码与之前的特化std::swap有明显不同,std::swap使用了标准的交换操作,而boost::swap通过ADL规则找到了全局名字空间的特化交换函数,实现了高效的交换.
 如果担心在全局名字空间编写自由函数swap会造成名字"污染",也可以把特化的swap加入到boost名字空间,或者其他ADL可以找到的名字空间
 
使用建议:
 boost提供了比std::swap更好的优化策略,如果写的类实现了高效的交换,或者想交换两个数组的内容,那么就使用boost::swap,它可以保证总能够找到最恰当的交换方法。

原创粉丝点击