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

[转载]http://blog.csdn.net/u011058765/article/details/46663827

考虑写出一个不抛出异常的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)语句时,它会拥有自动合适匹配的功能。更适合客户使用,实现接口的一致性和简易性。比如说:客户可以直接使用swap(w1,w2),而不是w1.swap(w2)。

下面我们来介绍当两个类都是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.

总结

条款25

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值