swap函数是c++中一个常用的函数,用于交换两对象的值,此外还用于在重载赋值运算符中处理自赋值情况和进行异常安全性编程(见下篇),标准模板库中swap的典型实现如下:

 namespace stl
{
template <typename T>
void Swap(T &lhs, T &rhs)
{
T temp(lhs);
lhs = rhs;
rhs = temp;
}
}

缺省版本的Swap函数包含三次对象的复制:lhs复制到temp,rhs复制到lhs,temp复制到rhs。然而在一些情况下,这种复制是无意义的,这会使得缺省版本Swap函数的效率低下,一种典型的情况出现在使用pimpl方法时:

——pimpl全称为pointer to implementation,即一个指针指向的对象包含真正的数据,例如:

 namespace jz
{
class PersonImpl
{
public:
PersonImpl(const std::string &name_, uint8_t sex_, uint8_t age_, const std::initializer_list<int> &int_il_)
: name(name_), sex(sex_), age(age_)
{
i_vec.assign(int_il_.begin(), int_il_.end());
}
//
PersonImpl(const PersonImpl &rhs)
: name(rhs.name), sex(rhs.sex), age(rhs.age), i_vec(rhs.i_vec)
{ }
//
PersonImpl& operator=(const PersonImpl &rhs)
{
name = rhs.name;
sex = rhs.sex;
age = rhs.age;
i_vec = rhs.i_vec;
}
private:
std::string name;
uint8_t sex : ; //标准没有规定char一定是8-bit,使用8-bit的unsigned int类型,需要包含<cstdint>
uint8_t age : ; //使用位域
std::vector<int> i_vec;
}; class Person
{
public:
Person(const std::string &name_, uint8_t sex_, uint8_t age_, const std::initializer_list<int> &int_il_)
: sptr_impl(std::make_shared<PersonImpl>(name_, sex_, age_, int_il_))
{ }
//
Person(const Person &rhs)
: sptr_impl(std::make_shared<PersonImpl>(*rhs.sptr_impl))
{ }
//
Person& operator=(const Person &rhs)
{
*sptr_impl = *rhs.sptr_impl;
}
private:
std::shared_ptr<PersonImpl> sptr_impl;
};

显然若对上面代码中的两个Person对象执行Swap操作,效率很低,因为显然只需将两个对象的智能指针成员sptr_impl进行交换,而缺省版本却会将指针指向的PersonImpl对象进行三次复制。因此,需要为Person特化Swap函数,编写一个高效的版本。

编写方法:

    ①为对象提供一个public的Swap成员函数,在该函数中高效地置换两个对象的值。

    ②在定义对象类的命名空间中提供一个非成员版本的Swap函数,调用成员函数版本的Swap函数。

    ③若编写的是类而不是类模板,在成员函数版本的Swap中特化标准库版本的Swap,根据名称查找法则,会优先调用特化版本的Swap。

  代码如下:

 namespace jz
{
inline void Person::Swap(Person &rhs)
{
using stl::Swap;
Swap(sptr_impl, rhs.sptr_impl);
} //
void Swap(Person &lhs, Person &rhs)
{
lhs.Swap(rhs);
}
}

  附注:

  swap函数的用处之一就是为类和类模板提供异常安全性保障,但这种保障基于一个假设:成员函数版本的Swap函数不抛出异常(缺省版本的Swap函数使用了拷贝构造函数和拷贝赋值运算符,都有可能抛出异常)。而因为高效率地Swap函数总是基于对内置类型的操作(比如指针),且内置类型上的操作不会抛出异常,所以上面的成员函数版Swap若要保证绝对不抛出异常,应该将智能指针改为内置类型的指针。

c++下为使用pimpl方法的类编写高效的swap函数的更多相关文章

  1. 在Linux下禁用IPv6的方法小结

    在Linux下禁用IPv6的方法小结--http://www.jb51.net/LINUXjishu/335724.html 这篇文章主要介绍了在Linux下禁用IPv6的方法小结,禁用IPv6的操作 ...

  2. 在Ubuntu 12.04下采用apt-get的方法安装Qt4

    在Ubuntu 12.04下采用apt-get的方法安装Qt4 注:之前发表的一篇博客是采用编译源码的方式安装Qt4,这是很有用的方式,因为源码安装对于所有系统都是通用的,其次,在使用交叉编译器的时候 ...

  3. linux下定时执行任务方法【转】

     之前就转过一篇关于定时任务的文章,前俩天用,还的翻出来看!!!再转一次,备用,,需要的时候不用麻烦找! ----------------------------------------------- ...

  4. 在Linux下和Windows下遍历目录的方法及如何达成一致性操作

    最近因为测试目的需要遍历一个目录下面的所有文件进行操作,主要是读每个文件的内容,只要知道文件名就OK了.在Java中直接用File类就可以搞定,因为Java中使用了组合模式,使得客户端对单个文件和文件 ...

  5. PHP环境下Memcache的使用方法

    原文:PHP环境下Memcache的使用方法 原文地址:http://www.2cto.com/kf/201503/384967.html 如今互联网崛起的时代,各大网站都面临着一个大数据流问题,怎么 ...

  6. Oracle 11g RAC环境下Private IP修改方法及异常处理

    Oracle 11g RAC环境下Private IP修改方法及异常处理 Oracle 11g RAC环境下Private IP修改方法及异常处理 一. 修改方法 1. 确认所有节点CRS服务以启动 ...

  7. php读取目录及子目录下所有文件名的方法

    本文实例讲述了php读取目录及子目录下所有文件名的方法,分享给大家供大家参考.具体实现方法如下: 一般来说php中读取目录下的文件名的方式确实不少,最简单的是scandir,具体代码如下: $dir= ...

  8. Windows 和  Linux 下 禁止ping的方法

    Windows 和Linux 下 禁止ping的方法 目的: 禁止网络上的其他主机或服务器ping自己的服务器 运行环境: Windows 03.08  linux 方法: Windows 03下: ...

  9. cocos2d-x3.2下获取文件夹下所有文件名的方法

    这里提供一个函数获取文件夹下所有文件名的方法,直接上代码了. 原文地址:http://blog.csdn.net/qqmcy/article/details/36184733 // //  Visib ...

随机推荐

  1. Hadoop NameNode 高可用 (High Availability) 实现解析

    转载自:http://reb12345reb.iteye.com/blog/2306818 在 Hadoop 的整个生态系统中,HDFS NameNode 处于核心地位,NameNode 的可用性直接 ...

  2. POJ2992:Divisors(求N!因子的个数,乘性函数,分解n!的质因子(算是找规律))

    题目链接:http://poj.org/problem?id=2992 题目要求:Your task in this problem is to determine the number of div ...

  3. react分享

    后台项目应用分享 后台项目应用分享 webpack + react + redux + antd 后台项目应用分享 策略篇 框架选择 组件化开发 组件?组件! CSS in JS下的样式开发思路 展示 ...

  4. ng-深度学习-课程笔记-1: 介绍深度学习(Week1)

    1 什么是神经网络( What is a neural network ) 深度学习一般是指非常非常大的神经网络,那什么是神经网络呢? 以房子价格预测为例,现在你有6个房子(样本数量),你知道房子的大 ...

  5. selenium-python读取XML文件

    首先这是我们要读取的XML文件 <?xml version="1.0" encoding="utf-8" ?><info> <ba ...

  6. deepin中crossover或playonlinux装完office后word无法输入中文的问题

    原因:office安装是自带了一个微软输入法 解决:装offce时进行自定义安装,在office共享功能里,把输入法去掉. 参考: https://jingyan.baidu.com/article/ ...

  7. SQL学习笔记一之初识数据库

    阅读目录 一 数据库管理软件的由来 二 数据库概述 三 mysql介绍 四 下载安装 五 mysql软件基本管理 六 初识sql语句 一 数据库管理软件的由来 基于我们之前所学,数据要想永久保存,都是 ...

  8. Django快速搭建博客系统

    Django快速搭建博客系统 一.开发环境 Windows 7(64bit) python 3.6   https://www.python.org/ Django 2.0  https://www. ...

  9. 2018-2019-1 20189215 《Linux内核原理与分析》第八周作业

    可执行程序工作原理 <庖丁解牛>第七章书本知识总结 "目标文件"是指编译器生成的文件,"目标"指的是目标平台,例如x86或x64,它决定了编译器使用 ...

  10. 20145204《java程序设计》课程总结

    ---恢复内容开始--- 20145204<java程序设计>课程总结 每周读书笔记链接汇总: · 20145204<java程序设计>第一周总结 · 20145204< ...