C++ swap函数(effective C++ 条款25)

标准库swap函数

我们首先看一下标准库的swap函数是如何实现的,它是一个定义在std命名空间的函数模板:

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

可以看到,标准库的swap实现调用了拷贝构造函数(对于非内置类型),并且有两次的赋值运算,这在很多情况下是不满足我们的效率需求的(大型对象的拷贝是毫无必要的操作,我们仅需要交换指针,若存在容器类型,调用容器类的swap明显是更加正确的操作)。在C++11中,我们有如下的优化:

template<typename T>
void swap(T& a,T&b) {
    T temp(std::move(a));
    a = std::move(b);
    b = std::move(temp);
}

移动方式的本质就是移交临时对象对资源的控制权,通常就是指针的替换,因此上述操作对存在移动构造和移动赋值运算的类来讲,已经可以基本满足要求,但是,对于未定义上述操作的类来讲,改进版本的swap操作并未有任何效率上的提升,因此,有必要定义类类型的swap。

copy and swap中的 swap操作

前一篇文章中关于copy and swap操作中提到了swap操作,作为成员函数的swap交换了两者指针:

class A {
private:
int *a;
public:
void swap(A& rhs) {
    using std::swap;
    swap(this->a,rhs.a);// 我们简单地交换了指针
}
};

我们稍后将解释关于using std::swap为何是必要的。

上述操作并没有解决问题,我们希望能够像调用普通swap函数操作一样调用swap(A &a,A&b),因此,我们下一步的操作就是在std命名空间内特化swap版本:

namespace std {
    template<>
    void swap<A>(A&a,A&b) {
        a.swap(b);
    }
}

在std空间内的特化版本满足C++标准的规定,这种扩充操作使得我们的特化版本对包含了std空间的文件都处于可见状态,因此,我们可以像以前一样使用swap进行交换:

using std::swap;
A a,b;
swap(a,b);

我们知道,C++允许对类模板全特化,但是对函数模板不允许全特化:

template<typename T>
// 以下定义不允许!
void swap<A<T>> (A<T>& a,A<T>& b) {
    a.swap(b);  
}

同样的,std内对swap的重载也不符合规定,我们的解决方案就是,在自定义的命名空间内定义swap函数:

namespace Astuff {
    template<typename T>
    class A {
    ...
    ...
    };
    template<typename T>
    void swap(A<T>&a,A<T> &b) {
        a.swap(b);
    }

};

这样,我们在当前的命名空间内就拥有了swap的完整定义,那么为什么在使用时要加using std::swap呢?这句声明会使std命名空间的swap暴露出来,编译器会自动在当前命名空间和std空间内寻找最符合当前函数调用的swap版本,因此,以下的写法完全错误:

A a,b;
std::swap(a,b);

这种写法直接调用了std空间内的swap函数,因此并不符合大多数情况下的需求,using版本才是最准确的版本:

using std::swap;
swap(a,b);
  • 2
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值