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. eclipse设置text file encoding UTF-8和文件的换行符 Unix 格式

    阿里华山版java开发手册代码格式第10条: 步骤:1.Window - Preferences, 2.左边选择 General - Workspace , 3.右边Text file encodin ...

  2. Spring Boot配置文件的加载顺序

    配置文件的加载顺序, 后加载的会覆盖先加载的:也就是properties配置文件的内容会替换掉.yml及.yaml文件的内容

  3. Python TypeError: __init__() got multiple values for argument 'master'(转)

    转自:https://stackoverflow.com/questions/33153404/python-typeerror-init-got-multiple-values-for-argume ...

  4. Yii2 redis 使用

    首先要安装一下redis的扩展 composer require yiisoft/yii2-redis 在配置文件中添加redis配置 'components' => [ .... 'redis ...

  5. <a>的javascript+jquery编程实例之删除(定位节点与事件绑定)

    相关jquery方法 parent(), remove() //上传图片 article_create.js article_edit.js function uploadAttachment() { ...

  6. 关于utf8mb4的使用

    针对mysql数据库存储一些特殊字符或者emoji的字符,所需要的编码类型.实际上基于efcore框架的情况下,codefirst自动迁移生成的数据库的默认编码格式,就是utf8mb4,以前的时候记得 ...

  7. string.Format 格式化

    1.格式化货币(跟系统的环境有关,中文系统默认格式化人民币,英文系统格式化美元) string.Format("{0:C}",0.2) 结果为:¥0.20 (英文操作系统结果:$0 ...

  8. vue组件上动态添加和删除属性

    1.vue组件上动态添加和删除属性 // 添加 this.$set(this.obj, 'propName', val) // 删除 this.$delete(this.obj, 'propName' ...

  9. win10如何安装mariadb

    一.下载.安装 1.下载mariadb(https://downloads.mariadb.org/),解压 2.进入bin目录下执行(管理员模型-powershell) .\mysqld.exe - ...

  10. css 垂直方向 margin 边距 重合

    1:控制两个相邻边盒子之间的距离,在A或者B盒子上用margin控制,就可以控制距离了. 2:父子级之间的元素,常规文档流中,只要垂直外边距直接接触就会发生合并.比如在写header标签时,想移动he ...