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

boost::swap的更多相关文章

  1. 使用Boost库(1)

    如何说服你的公司.组织使用Boost库 one of the most highly regarded and expertly designed C++ library projects in th ...

  2. boost开发指南

    C++确实很复杂,神一样的0x不知道能否使C++变得纯粹和干爽? boost很复杂,感觉某些地方有过度设计和太过于就事论事的嫌疑,对实际开发工作的考虑太过于理想化.学习boost本身就是一个复杂度,有 ...

  3. boost any库

    转: 原理 c++是一个强类型的语言,要实现一个万能类型可以考虑用void*来保存数据,然后用类型转换进行操作,如: class MyAny{ MyAny(void* input):content_( ...

  4. boost array使用

    #include <iostream> #include<boost/array.hpp> int main() { boost::array<int, 6> ar ...

  5. Boost源码剖析之:泛型指针类any

    C++是强类型语言,所有强类型语言对型别的要求都是苛刻的,型别一有不合编译器就会抱怨说不能将某某型别转换为某某型别,当然如果在型别之间提供了转换操作符或是标准所允许的一定程度的隐式转换(如经过非exp ...

  6. stl 比较和boost LessThanComparable

    C++ STL的几种常用“比较”概念简述   在C++的现行标准(C++ 98)中,由于没有类似“接口”这样的东西,我们在泛型编程时往往只能对模板类型作一些假设,要求其符合某个需求清单,也就是属于某个 ...

  7. boost源码剖析----boost::any

    boost源码剖析----boost::any 有的时候我们需要有一个万能类型来进行一些操作,这时候boost::any就派上用场了. boost::Any testInt(10); int val ...

  8. c++新特性与boost

    <Boost程序库探秘——深度解析C++准标准库>之试读 前一阵子还看到一篇文章,说C#要重蹈C++的覆辙,这里说的C++的覆辙是什么呢?是指C++语言过于臃肿的功能特性,导致学习人员的流 ...

  9. boost.compressed_pair源码剖析

    意义 当compressed_pair的某一个模板参数为一个空类的时候将对其进行“空基类优化”,这样可以使得compressed_pair占用的空间比std::pair的更小. 参考如下代码: #in ...

随机推荐

  1. 题解 CF1216A 【Prefixes】

    题目大意:给你一个长度为$n$($n$为偶数)的字符串,且这个字符串仅由$'a'$与$'b'$两种字符组成,要你用最少的操作次数使得 $s[i]!=s[i-1] (i/2=0,1≤i≤n)$(若字符串 ...

  2. 去除echarts饼状图的引导线

    series: { name: "流量占比分布", type: "pie", radius: ["40%", "60%" ...

  3. 题解-CSA Beta Round#1 Number Elimination

    Problem CSA-Beta Round#3 题意概要:给定 \(n\) 个数组成的序列,定义一次操作: 在当前序列中选择两个数,将其中较小的数从序列中删除(若两个数相同,则删除在序列中更靠前的) ...

  4. redis列表数据类型---list

    一.概述 redis列表是简单的字符串列表,按照插入顺序排序 可以添加一个元素到列表的头部(左边)或者尾部(右边) 一个列表最多可以包含2^32-1个元素(每个列表超过40亿个元素). 二.redis ...

  5. Go 操作 Mysql(三)

    什么是事务? 事务是数据库非常重要的部分,它具有四大特性(原子性.一致性.隔离性.持久性) 以下内容出自<高性能MySQL>第三版,了解事务的ACID及四种隔离级有助于我们更好的理解事务运 ...

  6. jq的ajax方法

    相较与js异步对象的繁琐,jq的ajax对象结构更加清晰 一:ajax对象简述 ajax(Asynchronous JavaScript and XML),异步的xml和js对象,主要用于在不刷新全局 ...

  7. js入门之内置对象Date

    一. Date对象 Math和Date对象的区别 Math对象和Date对象的区别 Math不是一个构造函数,里面提供的是静态成员 Date是一个构造函数 首先要通过new Date() 来创建日期实 ...

  8. Qt布局

    常用的布局方法 1. 水平布局类 QHBoxLayout 2. 垂直布局类 QVBoxLayout 3. 网格布局类 QGridLayout QHBoxLayout 对象横向排列开 QVBoxLayo ...

  9. java引用传递和值传递

    关于Java传参时是引用传递还是值传递,一直是一个讨论比较多的话题,有论坛说Java中只有值传递,也有些地方说引用传递和值传递都存在,比较容易让人迷惑.关于值传递和引用传递其实需要分情况看待,今天学习 ...

  10. 前台.cshtml得到session值方法

    方法一 <script> var s="@Session["visitor_name"]"; if(s=="")//解决报错问题 ...