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. Struts笔记3

    struts标签 form表单标签 Action:请求地址.直接写动作名称,不用写contextPath <s:form action="/user/register.action&q ...

  2. java8 : 流

    package day02.com.offcn.test; import java.io.IOException; import java.nio.charset.Charset; import ja ...

  3. Python-21-socket编程

    一.基础知识 1. C/S架构 C/S架构即客户机/服务器模式. 它可以分为客户机和服务器两层: 第一层:  在客户机系统上结合了界面显示与业务逻辑: 第二层:  通过网络结合了数据库服务器. 简单的 ...

  4. Ubuntu 18.04安装arm-linux-gcc交叉编译器

    Ubuntu 18.04安装arm-linux-gcc交叉编译器

  5. Sping Aop日志实现(五)--使用Mybatis注解保存日志

  6. entity-framework-core – 实体框架核心RC2表名称复数

    参考地址:https://docs.microsoft.com/zh-cn/ef/core/modeling/relational/tables http://www.voidcn.com/artic ...

  7. Html5知识精粹纪录

    1. HTML5文档的正文结构及新元素 正文结构: <header> <nav> <section> <aside> <footer> 深入 ...

  8. node中用的cookie-parser插件设置的max-age,和普通正常设置max-age的计算方式不一样

    在cookie-parser中通过max-age设置的cookie的过期时间是按照毫秒计算的; 在普通设置的时候max-age后面的值是按秒计算的;

  9. git 把其他分支上的文件拿来覆盖本地

    1:git checkout oldversion -- 文件地址 2: 一个分支从某个角度讲也像是一次commmit,也是有向无环图的一个点

  10. linux命令详解

    命令语法介绍 命令   [参数] [文件或路径] rm       -f                  /etc/hosts 注:命令和参数至少一个空格(可以多个连着写)      路径不带空格  ...