您的位置:首页 > 编程语言 > C语言/C++

【c++】拷贝控制具体分析

2014-07-11 14:57 253 查看
我们可以定义拷贝操作,使类的行为看起来像一个值或者像一个指针,这取决于如何拷贝指针成员。

当我们拷贝一个像值的对象时,副本和原对象是完全独立的,改变副本不会对原对象有任何影响,反之亦然。标准库容器和string类的行为像一个值。

当我们拷贝一个行为像指针的类的对象时,副本和原对象使用相同的底层数据,改变副本也会改变原对象,反之亦然。

浅拷贝,指的是在对象复制时,只是对对象中的数据成员进行简单的赋值,默认拷贝构造函数执行的也是浅拷贝。这样一来可能出现多个指针指向同一块内存的情况

在“深拷贝”的情况下,对于对象中动态成员,就不能仅仅简单地赋值了,而应该重新动态分配空间

一、行为像值的类(不同的类对象的指针数据成员指向独立的内存空间)

class HasPtr
{
public:
HasPtr(const HasPtr&) :ps(new string(*p.ps), i(p.i)){}
HasPtr& operator=(const HasPtr &);
~HasPtr(){ delete ps; }
private:
string *ps;
int i;
};
/*
通过先拷贝右侧运算对象,我们可以处理自赋值情况,并能保证异常发生时代码安全
*/
HasPtr& HasPtr::operator=(const HasPtr &rhs)
{
auto newp = new string(*rhs.ps);//拷贝底层string
delete ps;//释放旧内存
ps = newp;
i = rhs.i;
return *this;
}

HasPtr& HasPtr::operator=(const HasPtr &rhs)
{
delete ps;//释放旧内存
//如果rhs和*this是同一个对象,我们就将从已释放的内存中拷贝数据
ps = new string(*rhs.ps);
i = rhs.i;
return *this;
}


二、定义行为像指针的类

因为可能会有多个类的指针指向同一个地址,所以使用引用计数,引用计数是个指针,如果是个值得话,考虑下面情况(值得话每个对象都保存一个副本,互相独立)。

HasPtr p1("ljy");

HasPtr p2(p1);

HasPtr p3(p1);//p1,p2,p3指向相同的string,若引用计数是值的话,无法更新

class HasPtr
{
private:
string *ps;
int i;
int *use;
public:
HasPtr(const HasPtr &p) :ps(p.ps), i(p.i), use(p.use){ ++*use; }
HasPtr& operator=(const HasPtr&);
~HasPtr();
};

HasPtr::~HasPtr()
{
if (--*use == 0)
{
delete ps;
delete use;
}
}

HasPtr& HasPtr::operator=(const HasPtr &rhs)
{
++*rhs.use;
if (--*use == 0)
{
delete ps;
delete use;
}
ps = rhs.ps;
i = rhs.i;
use = rhs.use;
return *this;
}


View Code
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: