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

#include<algorithm>
#include<iostream>
#include<cstdio>
#include<vector>
class WidgetImpl{
    //......
    std::vector<int>v;
};
class Widget
{
public:
    void swap(Widget& other){
        //原书给的是
        using std::swap;
        swap(pImpl,other.pImpl);
        //std::swap(pImpl,other.pImpl);
        //调用std标准中的swap函数,也能得出同样的结果
        //可能很多人也觉得直接调用std标准中的函数就可以了
        //书后面讲到,用上面的写法
        //编译器会首先在全局作用域或者T所在的命名空间
        //这里就是WidgetImpl类型所在的命名空间中
        //查找是否有专属的swap,如果没有才调用标准中的swap
        //使得程序更为鲁棒
    }
private:
    WidgetImpl *pImpl;
    //这时候直接交换指针所指内容就可以了
    //如果调用默认的swap函数,就会深拷贝vector
};
namespace std{
    template<>
    void swap<Widget>(Widget& a,Widget& b){
        //我们不能改变std命名空间内的任何东西
        //但可以为标准templates制造特化版本
        //使它属于我们自己的class
        a.swap(b);
        //为了函数的封装性,尽量少声明friend-function
        //所以提供一个接口,供特化版本swap使用
        //并且与STL容器有一致性
        cout << "call Widget swap function" << endl;
    }
}
int main()
{
    Widget a,b;
    using std::swap;
    swap(a,b);
}

如果刚才的Widget和WidgetImpl都是class templates而非classes。。。
再刚才那样子写就不对了。。。c++不允许在function templates身上偏特化,而允许对class templates身上偏特化。。。
惯常,要想偏特化一个function templates,可以添加一个重在版本。。。
但是客户可以全特化std内的templates,但不可以添加新的templates(classes或functions或其他东西)到std里面

所以我们只能放到其他命名空间中或者global中(但是在global中放太多东西会导致不整齐吧,原书作者这样说的吧)

#include<algorithm>
#include<iostream>
#include<cstdio>
#include<vector>
namespace WidgetStuff{
    template<typename T>
    class WidgetImpl{
        //......
        std::vector<T>v;
    };
    template<typename T>
    class Widget
    {
    public:
        void swap(Widget& other){
            using std::swap;
            swap(pImpl,other.pImpl);
        }
    private:
        WidgetImpl<T> *pImpl;
    };
    template<typename T>
    void swap(Widget<T>& a,Widget<T>& b){
        a.swap(b);
        //non-member swap函数
        //这里并不属于std命名空间
        std::cout << "call Widget swap function" << std::endl;
    }
}
template<typename T>
void doSomething(T& lsh,T& rsh)
{
    using std::swap;
    //C++名称查找法则确保将找到global作用域和T所在命名空间内
    //的任何T专属的swap,如果没有T专属的,则使用std内的swap
    puts("&&&&&&&&&&&&&&&");
    swap(lsh,rsh);
    puts("---------------");
    //这里如果调用std::swap()那便强迫编译器只认std内的swap
}
int main()
{
    int a,b;
    doSomething(a,b);
    WidgetStuff::Widget<int>c,d;
    doSomething(c,d);
}

图片
成员版swap绝对不抛出异常,这个约束只施于成员版
当你写下自定义版的swap,往往不光提供高效置换对象的方法,而且不抛出异常。因为高效swap几乎总是基于对内置类型的操作,而内置类型上的操作绝对不会抛出异常

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值