• 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而言全新的东西。

    =======================================================================
    所有内容都是用BSD条款。 Copyright (C) by CloudFeng.
  • 相关阅读:
    马哥博客N46第七次作业
    马哥博客N46第五次作业
    马哥博客N46第一月考
    马哥博客N46第四次作业
    马哥博客作业第三周
    马哥博客N46第二次作业
    马哥博客N46第一次作业
    马哥博客作业第四周
    马哥博客作业第二周
    后端跨域问题的解决
  • 原文地址:https://www.cnblogs.com/cloudfeng/p/4354552.html
Copyright © 2020-2023  润新知