Effective C++ 条款25

来源:互联网 发布:淘宝卖家认证复核 编辑:程序博客网 时间:2024/05/16 18:55

考虑写出一个不抛出异常的swap函数

本节讲解如何自定义一个高效的swap函数

对于std名空间中的swap缺省函数如下所示

namespace std{    template<typename T>    void swap(T& a, T& b)    {        T temp(a);        a=b;        b=temp;    }}class WidgetImpl{public:    ……private:    int a,b,c;              //数据很多,复制意味时间很长    std::vector<double> b;    ……};

我们可以看到,当交换对象的数据很大时,以上swap的执行效率会很慢,为了改变这种状况,作者提出以下方法;

重新定义一个类

class Widget{public:    Widget(const Widget& rhs);    Widget& operator=(const Widget& rhs    {        ……          //复制Widget时,复制WidgetImpl对象                      *pImpl=*(ths.pImpl);        ……    }    ……private:    WidgetImpl* pImpl;//指针,含有Widget的数据};

如果置换两个Widget对象值,只需要置换其pImpl指针,那么效率就会很高。
那么怎样定义swap呢?
如下:

calss Widget{public:    ……    void swap(Widget& other)    {        using std::swap;//这个声明有必要        swap(pImpl, other.pImpl);    }    ……};namespace std{    template<> //修订后的swap版本    void swap<Widget>(Widget& a, Widget& b)    {        a.swap(b);  //调用其成员函数    }}Widget w1,w2;swap(w1,w2);//调用名空间的全特化Widget版本的swap.

从上面的代码我们可以看出完成了我们的目的,实现两个WidgetImpl对象交换,只交换他们的指针。当然这里需要构造出一个交换类Widget,需要全特化Widget 类型的swap,需要在函数体内定义member函数swap。

那么,读者就迷茫了,绕了一大圈,怎么不直接调用成员函数swap,这是因为当你用swap(a,b)语句时,它会拥有自动合适匹配的功能。更适合客户使用,实现接口的一致性和简易性。

下面我们来介绍当两个类都是template,如何解决上面的问题?
如下:

template<typename T>class WidgetImpl{……};template<typename T>class Widget{……};

我们可以重新命名一个名空间如下:

namespace WidgetStuff{   ……//模板化的WidgetImpl等   template<typename T>//内含swap函数   class Widget{……};   ……   template<typename T>   void swap(Widget<T>& a,//non-member,不属于std命名空间             Widget<T>& b)   {       a.swap(b);   }}Widget<int> w1,w2;swap(w1,w2);//调用名空间WidgetStuff的Widget<int>版本的swap.
0 0
原创粉丝点击