copy and swap 技术 (读Effecitive c++ item11的引申)
从item11中直接看Scott关于copy and swap
的描述会有些迷茫,copy and sway的实施要建立在类能够对资源自动管理的基础上,也就是在类解析的时候类能够自己释放资源,没有这个前提交代和示例,大部分c++使用者很难跟上作者Scott的思路。
关于copy and swap技术的描述,有一篇博客描述的很不错。 https://blog.csdn.net/xiajun07061225/article/details/7926722
推荐参考。
本文的重点是补充Effective c++ item11这块的缺失, 让对本章节的理解能更顺畅一些。
回顾下item11中copy and swap
的引出背景,是针对下面的一段拷贝赋值操作的重载实现
class Widget
{
...
private:
Bitmap* pb;
}
Widget& Widget::operator=(const Widget& rhs)
{
Bitmap* pOrig = pb;
pb = new Bitmap(*rhs.pb);
delete pOrig;
return *this;
}
对于上述的类Widget定义是没有办法直接使用copy and swap
技术的,原因是这个Widget的类定义,没有实现对资源的自动管理。也就是说他的析构函数上没有对Bitmap* pb
进行释放。以a=b为例,copy and swap
的核心是,先生成b的一份复制体c,然后把a里面旧的数据和资源与c进行交换,然后析构c,在析构c的时候,会把a原来旧的资源释放掉。所以要求c在析构的时候能够自己释放资源。同时我们还需要实现一个swap函数,用户交换a与c的数据。
综上要使用copy and swap
技术,Widget类还需要一个能够管理资源的析构函数, 还需要一个swap函数,还需要一个拷贝构造函数(需要用这个函数生成复制体)。有了这些前提条件,才能使用该技术。
typedef int Bitmap;
const int MAX = 10;
class Widget
{
public:
Widget()
{pb = new int[MAX]();}
Widget(const Widget&rhs)
{pb = new int[MAX]();
std::copy(rhs.pb, rhs.pb+MAX, pb);}
void swap(Widget&a, Widget &c)
{using std::swap;swap(a.pb,b.pb);}
~Widget()
{delete[] pb;}
Widget& operator= (const Widget& rhs)
{
Widget tmp(rhs);
swap(*this,tmp);
return *this;
}
private:
Bitmap* pb;
}
在上述的拷贝赋值函数中,我们先利用拷贝构造函数生成了一个复制体tmp,注意tmp里面的资源是独立的,自己维护的,只不过资源内容和复制主体一模一样而已。
之后通过swap,把*this 内的数据与复制体交换。这里交换的只是指针索引,实际数据资源的位置并没有变化,只是归属发生了变化。
最后return后,我们如愿赋值到了我们想要的数据。赋值前的老数据我们交换给了tmp,并且在函数体退出后,tmp自动释放了老数据。
网友评论