Effective C++笔记_条款25考虑写出一个不抛出异常的swap函数

  1 // lib中的swap
  2 namespace std {
  3     template<typename T>
  4     void swap (T& a, T& b)
  5     {
  6         T temp(a);
  7         a = b;
  8         b = temp;
  9     }
 10 }
 11
 12 // 缺点:需要赋值大量的数据,但是有的时候并不要复制如此多的内容
 13 class WidgetImpl {
 14 public:
 15     //...
 16 private:
 17     int a, b, c;
 18     std::vector<double> v;     // 可能有很多数据,以为复制时间很长
 19     //...
 20 };
 21
 22 class Widget {
 23 public:
 24     Widget(const Widget& rhs);
 25     Widget& operator= (const Widget& rhs)
 26     {
 27         //...
 28         *pImpl = *(rhs.pImpl);
 29         //....
 30     }
 31 private:
 32     WidgetImpl *pImpl;
 33 };
 34
 35 // 对于上面这个实例来说,只需要交换指针就好了,没有必要进行全部的值的交换。
 36 // 为了解决这个问题,需要将std::swap针对Widget特化。说白一点就是专门为Widget
 37 // 设计一个swap函数
 38 // 解决方案
 39 class Widget {
 40 public:
 41     Widget(const Widget& rhs);
 42     Widget& operator= (const Widget& rhs)
 43     {
 44         //...
 45         *pImpl = *(rhs.pImpl);
 46         //....
 47     }
 48
 49     // 注意哟,重点到了.实现真正的置换工作
 50     void swap(Widget& other)
 51     {
 52         using std::swap;
 53         swap(pImpl, other.pImpl);
 54     }
 55
 56 private:
 57     WidgetImpl *pImpl;
 58 };
 59
 60 // 注意哟,下面是针对Widget类的特化swap,它调用Widget的swap函数
 61 namespace std {
 62     template<>       // 1.全特化
 63     void swap<Widget>(Widget& a, Widget& b)   // 2.表明这个swap函数专门给Widget特化的
 64     {
 65         a.swap(b);
 66     }
 67 }
 68
 69 // 面对class templates 又如何呢
 70 template<typename T>
 71 class WidgetImpl {
 72     //...
 73 };
 74
 75 template<typename T>
 76 class Widget {
 77     //...
 78 };
 79
 80 /*
 81  错误哟:C++只允许对class templates 偏特化,在function templates偏特化是行不通的
 82  客户可以全特化std内的templates(template<>),但是不可以添加新的templates(或classes
 83  或functions或其他任何东西)到std里头。
 84 */
 85 namespace std {
 86     template<typename T>
 87     void swap< Widget<T> > (Widget<T>& a, Widget<T>& b)
 88     {
 89         a.swap(b);
 90     }
 91 };
 92
 93 // ----- solution  -----
 94 namespace WidgetStuff {
 95     class WidgetImpl {
 96     public:
 97         //...
 98     private:
 99         int a, b, c;
100         std::vector<double> v;     // 可能有很多数据,以为复制时间很长
101         //...
102     };
103
104     class Widget {
105     public:
106         Widget(const Widget& rhs);
107         Widget& operator= (const Widget& rhs)
108         {
109             //...
110             *pImpl = *(rhs.pImpl);
111             //....
112         }
113
114         // 注意哟,重点到了.实现真正的置换工作
115         void swap(Widget& other)
116         {
117             using std::swap;
118             swap(pImpl, other.pImpl);
119         }
120
121     private:
122         WidgetImpl *pImpl;
123     };
124
125     template<typename T>
126     void swap(Widget<T>& a, Widget<T>& b)
127     {
128         a.swap(b);                   // 调用Widget中的swap函数
129     }
130 }

总结: 

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

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

调用swap时应该针对std::swap使用using声明式,然后调用swap并且不带任何“命名空间资格修饰”。

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

时间: 2024-10-23 08:55:27

Effective C++笔记_条款25考虑写出一个不抛出异常的swap函数的相关文章

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

1. swap是STL的一部分,后来成为异常安全性编程(exception-safe programming)(见条款29)的一个重要脊柱,标准库的swap函数模板定义类似以下: namespace std{ template<typename T> swap(T& lhs,T& rhs){ T temp(lhs); lhs=rhs; rhs=temp; } } 只要T类型支持拷贝构造以及拷贝赋值,标准库swap函数就会调用T的拷贝构造函数和拷贝构造操作符完成值的转换,但对于某

《Effective C 》资源管理:条款25--考虑写出一个不抛出异常的swap函数

条款25考虑写出一个不抛出异常的swap函数 条款25:考虑写出一个不抛出异常的swap函数 swap是STL中的标准函数,用于交换两个对象的数值.后来swap成为异常安全编程(exception-safe programming,条款29)的脊柱,也是实现自我赋值(条款11)的一个常见机制.swap的实现如下: namespace std{ template<typename T> void swap(T& a, T& b) { T temp(a); a=b; b=temp;

读书笔记_Effective_C++_条款二十五: 考虑写出一个不抛出异常的swap函数

在之前的理论上调用对象的operator=是这样做的 void swap(A& x) { std::swap(a, x.a); } A& operator=(const A& a) { A temp = a; swap(temp); return *this; } 上面的代码看起来有点麻烦,但它是一个好办法. 我们可以在std里面特化我们的swap class A { private: int a; public: void swap(A& x)//防止写成friend,我

条款25:考虑写出一个不抛异常的swap函数

条款25:考虑写出一个不抛异常的swap函数 swap函数在C++中是一个非常重要的函数,但实现也非常复杂. 看一个缺省的std::swap函数的实现 namespace std { template<typename T> void swap( T& a , T& b) { T temp(a); a = b; b = temp } } ①内置类型的调用 int a = 2; int b =3; std::swap(a, b); cout<<"a:&quo

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

记住: ★当std::swap对你的类型效率不高时,提供一个swap成员函数,并确定其不抛出异常 ★若你提供一个member swap,也该提供一个non-member swap来调用前者.对于classes(而非templates),也请特化std::swap ★调用swap时应针对std::swap使用using声明式,然后调用swap并且不带任何“命名空间资格修饰” ★为“用户定义类型”进行std templates全特化是好的,但千万不要尝试在std内加入某些对std而言全新的东西 --

Effective C++笔记_条款46 需要类型转换时请为模板定义非成员函数

看这个章节的时候又跑回去看了一下 条款 24,本章的例子就是基于下面这个例子而来的.在 item 24 中,支持混合运算的示例代码如下: 1 class Rational { 2 public: 3 Rational(int numerator = 0, int denominator = 1); 4 int mumerator() const; 5 int denominator() const; 6 private: 7 int numerator; 8 int denominator; 9

Effective C++ Item 25 考虑写出一个不抛异常的swap函数

本文为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

Effetive C++_笔记_条款06_若不想使用编译器自动生成的函数,就该明确拒绝

(整理自Effctive C++,转载请注明.整理者:华科小涛@http://www.cnblogs.com/hust-ghtao/) 通常如果你不希望class支持某一特定机能,只要不声明对应函数就是了.但这个策略对copy构造函数和copy assignment操作符却不起作用,你如果不声明它们,而某些人尝试调用它,编译器会为你声明它们. 这把你逼到了一个困境.如果你不声明copy构造函数和copy assignment操作符,编译器可能为你产出一份,于是你的clas支持copying.如果

Effective C++笔记_条款43 学习处理模板化基类内的名称

开篇就来了一个示例代码,整个这个小节就围绕这个示例代码来描述模板化基类内的名称(函数).主要是因为C++知道base class templates有可能被特化,而那个特化版本肯呢个不提供和一般性template相同的接口.因此它往往拒绝在templatized base classes(模板化基类)内寻找继承而来的名称. 1 class CompanyA { 2 public: 3 //... 4 void sendCleartext(const std::string& msg); 5 vo