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

版权声明:仅供参考与学习交流 https://blog.csdn.net/lym940928/article/details/81989377

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

Consider support for a non-throwing swap.
本章作为设计与声明最后一章,内容较长,分为三部分。

swap

swap是一个有趣的函数。
原本它只是STL的一部分,而后则成为异常安全性编程(exception-safe programming)的主体,以及后来用于处理自我赋值可能性(条款11)的一个常见机制。因此,swap的实现是非常重要的。

swap的缺省实现

所谓的swap(置换)两对象的值,指的就是将两对象的值彼此赋予对方。在默认的情况之下,swap动作可以由STL提供的swap算法来实现:

namsespace std {
    tempate<typename T>
    void swap(T& a, T& b)
    {
        T temp(a);
        a = b;
        b =temp;
    }
}

只要类型T支持copying(通过copy构造函数和copy assignment操作符来完成),缺省的swap实现代码就会自动置换类型为T的对象,我们并不需要额外的工作。

这种缺省的实现比较简单,涉及到了三个对象的复制:

  • a复制到temp
  • b复制到a
  • temp复制到b。

但是对于某些类型而言,这些复制动作并没有必要!

其中最主要的即“以指针指向一个对象,内含真正数据”的类型。
这种类型最常见的表现形式就是“pimpl手法”(pointer to implementation)
如果以这种手法设计Widget class:

class WidgetImpl {
public:
    ...
private:
    int a, b, c;      //可能有许多数据,意味着复制时间很长
    std::vector<double> v;
    ...
};

class Widget {          //该class使用pimpl手法
public:
    Widget(const Widget& rhs);     //复制Widget时,令它复制其WidgetImpl对象
    Widget& operator=(const Widget& rhs)   //operator=的实现见条款10~12
    {
        ...
        *pImpl = *(rhs.pImpl);
        ...
    }
    ...
private:
    WidgetImpl* pImpl;    //指针,所指的对象就是内含Widget数据
};

一旦我们需要置换两个Widget对象的值,我们唯一需要做的就是置换其pImpl指针而已。
但是,缺省的swap并不知道这一点!它不仅会复制三个Widgets,还会复制三个WidgetImpl对象!效率一下子就变得很低了。

猜你喜欢

转载自blog.csdn.net/lym940928/article/details/81989377