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 函数的编写的主要内容,如果未能解决你的问题,请参考以下文章
Problem E: 编写函数:Swap (I) (Append Code)