本文为senlie原创,转载请保留此地址:http://blog.csdn.net/zhengsenlie

经验:当std::swap对你的类型效率不高时,提供一个swap成员函数,并确定这个函数不抛出异常

演示样例:

stl里的swap算法

namespace std{
template<typename T>
void swap(T &a, T &b){
T temp(a);
a = b;
b = temp;
}
} //“pimpl手法”(pointer to implementation) --> 文件间的编译依存度
class WidgetImpl{
public:
//...
private:
int a, b, c;
std::vector<double> v;
//...
} class Widget{
public:
Widget(const Widget &rhs);
Widget &operator=(const Widget &rhs){ //返回的为什么是引用?--> 就应该是引用,參见Item10令operator=返回一个reference to *this。
//这里和Item28不一样,那里说的是不要返回handler指向对象 内部 成分。 //...
*pImpl = *(rhs.pImpl);
//...
}
//...
private:
WidgetImpl *pImpl;
}

解析:一旦要转换两个Widget对象值,我们唯一须要做的就是转换其pImpl指针。但缺省的swap算法不知道这一点。它不仅仅复制三个Widgets,还复制三个WidgetImpl对象。



纠正:将std::swap针对Widget特化

通常我们不被同意改变std命名空间的不论什么东西。但能够为标准template制造特化版本号

namespace std{ //这是std::swap针对“T是Widget”的特化版本号。

眼下还不能通过编译
template<>
void swap<Widget>(Widget &a, Widget &b){
swap(a.pImpl, b.pImpl);
}
}

经验:假设你提供一个member swap。也该提供一个non-member swap用来调用前者。对于 classes(而非templates)。也请特化std::swap



演示样例:

namespace WidgetStuff{
class Widget{ //能正常编译,且与STL容器有一致性。 由于全部STL容器也都提供有public swap成员函数和std::swap特化版本号
public:
//...
void swap(Widget &other){ //调用swap时应针对std::swap使用using声明式。然后调用swap而且不带不论什么“命名空间资格修饰”
using std::swap;
swap(pImpl, other.pImpl);
} //...
};
void swap(Widget &a, Widget &b){ //non-member swap 函数。这里并不属于std命名空间
a.swap(b);
}
}
namespace std{
template<>
void swap<Widget>(Widget &a, Widget &b){
a.swap(b);
}
}

经验:为“用户定义类型”进行std templates全特化是好的。但千万不要尝试在std内增加某些对std而言全新的东西

演示样例:

template<typename T>
class WidgetImpl{
//...
}
template<typename T>
class Widget{
//...
} namespace std{ //错误,不合法 --> function template仅仅能全特化。不能偏特化
template<typename T>
void swap<Widget<T> >(Widget<T> &a, Widget<T> &b){
a.swap(b);
}
} namespace std{
template<typename T> //std::swap的一个重载版本号,不合法 --> std不同意加入新的的templates
void swap(Widget<T> &a, Widget<T> &b){
a.swap(b);
}
}

Effective C++ Item 25 考虑写出一个不抛异常的swap函数的更多相关文章

  1. EC读书笔记系列之13:条款25 考虑写出一个不抛异常的swap函数

    记住: ★当std::swap对你的类型效率不高时,提供一个swap成员函数,并确定其不抛出异常 ★若你提供一个member swap,也该提供一个non-member swap来调用前者.对于cla ...

  2. Effective C++:条款25:考虑写出一个不抛异常的swap函数

    (一) 缺省情况下swap动作可由标准程序库提供的swap算法完毕: namespace std { template<typename T> void swap(T& a, T& ...

  3. [Effective C++ --025]考虑写出一个不抛异常的swap函数

    引言 在我的上一篇博客中,讲述了swap函数. 原本swap只是STL的一部分,而后成为异常安全性编程的脊柱,以及用来处理自我赋值可能性. 一.swap函数 标准库的swap函数如下: namespa ...

  4. 《Effective C++》item25:考虑写出一个不抛异常的swap函数

    std::swap()是个很有用的函数,它可以用来交换两个变量的值,包括用户自定义的类型,只要类型支持copying操作,尤其是在STL中使用的很多,例如: int main(int argc, _T ...

  5. Effective C++ -----条款25:考虑写出一个不抛异常的swap函数

    当std::swap对你的类型效率不高时,提供一个swap成员函数,并确定这个函数不抛出异常. 如果你提供一个member swap,也该提供一个non-member swap用来调用前者.对于cla ...

  6. 【25】考虑写出一个不抛异常的swap函数

    1.swap交换对象值,std提供了实现方法模版的实现,它的实现是交换对象值. namespace std { template<typename T> void swap(T& ...

  7. 考虑实现一个不抛异常的swap

    Effective C++:参考自harttle land 类的swap实现与STL容器是一致的:提供swap成员函数, 并特化std::swap来调用那个成员函数. class Widget { p ...

  8. 输入一个数字n 如果n为偶数则除以2,若为奇数则加1或者减1,直到n为1,求最少次数 写出一个函数

    题目: 输入一个数字n  如果n为偶数则除以2,若为奇数则加1或者减1,直到n为1,求最少次数  写出一个函数 首先,这道题肯定可以用动态规划来解, n为整数时,n的解为 n/2 的解加1 n为奇数时 ...

  9. java————数组 简单写出一个管理系统

    数组的特点 1,  数组是一块连续的空间,下标描述空间的位置. 2,  下标从0开始,最大下标为数组长度—1.(*.length-1) 3,  数组元素都是变量.(就是每个下标对应的内容).变量的类型 ...

随机推荐

  1. 从jscript脚本混淆说起

    转载:http://www.freebuf.com/column/144897.html 脚本病毒是一个一直以来就存在,且长期活跃着的一种与PE病毒完全不同的一类病毒类型,其制作的门槛低.混淆加密方式 ...

  2. 针对各地项目icomet停止服务的临时处理办法

    1.编辑一个脚本 vi /usr/local/watchicomet.sh #!/bin/bash sn=`ps -ef | grep ./icomet-server | grep -v grep | ...

  3. laravel 安装碰到的问题:全局安装 Laravel Installer,然后用下面的指令创建新项目: laravel new blog报连接超时解决方案

    在执行laravel new project 的时候报错 cURL error 7: Failed to connect to cabinet.laravel.com port 80: Timed o ...

  4. Python_Tips[0] -> 关于 import

    关于 import 1 import import可用于导入一个Python的标准模块,包括.py文件或带有__init__.py的文件目录. 在Python中,import一个模块后,若再次impo ...

  5. python 字符串最长公共前缀

      编写一个函数来查找字符串数组中的最长公共前缀. 如果不存在公共前缀,返回空字符串 "". 示例 1: 输入: ["flower","flow&qu ...

  6. 6.NFC之非NDEF格式

    先看流程图 使用步骤: 第一步:声明权限 <!-- 允许应用程序使用NFC功能 --> <uses-permission android:name="android.per ...

  7. 【转载】GCC 预处理器选项

    预处理器选项(Preprocessor Option) 下列选项针对C预处理器,预处理器用在正式编译以前,对C 源文件进行某种处理. 如果指定了`-E'选项, GCC只进行预处理工作.下面的某些选项必 ...

  8. 我的一次Postgre数据库Insert 、Query性能优化实践

    一.前言 以前的系统由于表设计比较复杂(多张表,表与表直接有主从关系),这个是业务逻辑决定的. 插入效率简直实在无法忍受,必须优化.在了解了Postgre的Copy,unlogged table 特性 ...

  9. 使用size()方法输出列表中的元素数量。需要注意的是,这个方法返回的值可能不是真实的,尤其当有线程在添加数据或者移除数据时,这个方法需要遍历整个列表来计算元素数量,而遍历过的数据可能已经改变。仅当没有任何线程修改列表时,才能保证返回的结果是准确的。

    使用size()方法输出列表中的元素数量.需要注意的是,这个方法返回的值可能不是真实的,尤其当有线程在添加数据或者移除数据时,这个方法需要遍历整个列表来计算元素数量,而遍历过的数据可能已经改变.仅当没 ...

  10. Windows环境下,用netstat命令查看某个端口号是否占用

    目标:在Windows环境下,用netstat命令查看某个端口号是否占用,为哪个进程所占用. 操作:操作分为两步:(1)查看该端口被那个PID所占用;方法一:有针对性的查看端口,使用命令 Netsta ...