boost::swap

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规则找到全局名字空间的特化交换函数,实现高效的交换。

猜你喜欢

转载自www.cnblogs.com/kloseer/p/12069506.html
今日推荐