swap 函数的编写

Posted 小键233

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了swap 函数的编写相关的知识,希望对你有一定的参考价值。

swap 函数用来交换两个变量的值,C++ 标准库提供了这个函数。

前面的博客也有提到 copy and swap 技术,可以处理自我交换的情况。
那一个典型的实现就是这样的:

template<typename T>
void swap(T& a, T& b)

    T temp(a);
    a = b;
    b = temp;

*C++ 标准库就提供了这个函数,所以并不用自己去手动编写这段代码。

简单易懂的函数。

现在我们来讨论复杂一点的情况,如何设计一个swap 函数用来处理“以指针指向一个对象,内含真正的数据”这样的类型。
有点拗口是吧,嗯,那来看看代码是长什么样的:

struct Data

;

class SomeClass

    Data* ptd;
public:
    SomeClass()
    
        ptd = new Data;
    
    SomeClass(const SomeClass& ins)
    
        ptd =  new Data(*ins.ptd);
    
    ~SomeClass()
    
        delete ptd;
    
    SomeClass& operator = (const SomeClass& ins)
    
        *ptd = *ins.ptd;  //复制时,只要让它们的指针指向的对象进行复制就可以了
        return *this;
    
;

这种设计称为“pimpl 手法”(pointer to implementation)

这时候一旦置换两个对象,效率就没有那么高,因为我们想要的就是简单地置换内部的指针值而已。

那解决方法就是全特化(total template specialization)std 中的swap 函数。

namespace std

    template<>
    void swap<SomeClass>(SomeClass& a, SomeClass& b)
    
        swap(a.ptd, b.ptd);//由于类的封装性,这个编译不通过
    

有趣的是,在std 中,它并不允许你添加新的东西进去(建议这么做,如果你非要添加的话,它也只能两手一摊,被逼无奈),但是允许你特化标准的templates实现。

这是我们想要的,但是因为数据的封装性,还需要再修改一下,于是变成这样子:

struct Data

;

class SomeClass

    Data* ptd;
public:
    SomeClass()
    
        ptd = new Data;
    
    SomeClass(const SomeClass& ins)
    
        ptd =  new Data(*ins.ptd);
    
    ~SomeClass()
    
        delete ptd;
    
    SomeClass& operator = (const SomeClass& ins)
    
        *ptd = *ins.ptd;  //复制时,只要让它们的指针指向的对象进行复制就可以了
        return *this;
    

    void swap(SomeClass& b)
    
        std::swap(ptd, b.ptd);  //指明使用std 的swap版本呢
    
;
namespace std

    template<>
    void swap<SomeClass>(SomeClass& a, SomeClass& b)
    
        a.swap(b);
    

到目前为止,一切都挺好,我们也得到了想要的实现。

现在,我们再变一下,把SomeClass 变成模板,于是代码变成这样子:

template<typename Data> //现在Data 是typename 的参数
class SomeClass

    ...
;

namespace std //偏特化不被允许

    template<typename T>
    void swap<SomeClass<T> >(SomeClass<T> & a, SomeClass<T> & b)
    
        a.swap(b);
    

因为SomeClass是个模板类了,我们也相应地改变swap 函数。
但是,注意,C++ 并不允许函数偏特化(partially specialize),它只允许对class 进行偏特化。
解释一下:

template<typename T>
class Link
;

template<typename T>
class FreeLink:public Link<T>  //类的偏特化,ok
;

那怎么去编写一个swap 函数,用于模板化的Someclass 呢?
答案是,依然编写一个non-member 函数的swap , 去调用member 的swap 函数。但是不把它放入命名空间std 中


//前面不能有using namespace std;
//如果有,要么改swap 函数名称,要么另写一个自己的namespace ,把swap丢进去
template<typename T>
void swap(T& a, T& b)

    a.swap(b);

那现在存在的swap 版本函数有:

std::swap; 
swap; //自己编写的swap ,调用的时候,可以通过命名空间指明

[参考资料]
[1] Scott Meyers 著, 侯捷译. Effective C++ 中文版: 改善程序技术与设计思维的 55 个有效做法[M]. 电子工业出版社, 2011.
(条款25:考虑写出一个不抛异常的swap 函数)

以上是关于swap 函数的编写的主要内容,如果未能解决你的问题,请参考以下文章

编写一个函数swap,将指定数组按照从小到大的顺序排序,

编写可读代码的艺术 PDF下载

Problem E: 编写函数:Swap (I) (Append Code)

急!IE(工业工程)常用的 excel 图表都有哪些?谢谢!!

swap 函数的编写

来扒扒机械工业出版社免费开放的电子好书