在C++中,当一个类为“空”时,里面真的为空吗?不是的,里面有四个函数。分别是构造函数,析构函数,拷贝构造函数,重载赋值操作符。
class Test{
};
等价于
class Test{
public:
Test();
Test(const Test& t); //拷贝构造函数,仅仅完成浅拷贝
Test& operator= (const Test& t); //重载赋值操作符,仅完成浅赋值
~Test();
};
拷贝构造函数和重载赋值操作符有什么区别?
Test t1;
Test t2(t1) // 等价于Test t2 = t1,此时调用拷贝构造函数,即初始化时调
用拷贝构造函数
Test t3;
t3 = t1; //这里为赋值操作,调用赋值操作
浅拷贝和浅赋值存在的问题:
class Test{
int i;
int *mptr; //使用系统资源
public:
Test(int j = 0)
{
mptr = new int; //分配资源
*mptr = j;
}
Test(const Test& t) //浅拷贝
{
i = t.j;
mptr = t.mptr;
*mptr = *(t.mptr);
}
Test& operator= (const Test& t) //浅赋值
{
if(this != &t) // 不能自赋值
{
i = t.j;
mptr = t.mptr;
*mptr = *(t.mptr);
}
return *this; //确保可以连续赋值
}
void mydelete(void)
{
delete mptr;
}
};
Test t1(10);
Test t2 = t1; //等价于Test t2(t1),这里调用浅拷贝构造函数;
...
mydelete();
t2,mydelete();
这时会发生什么情况?会出现内存错误。因为在t2的初始化时调用了系
统默认提供的浅拷贝函数,会将t1.mptr直接赋值给t2.mptr,使得
t1.mptr和t2.mptr指向同一段堆空间,然后调用t1,mydelete(),
t2,mydelete()会释放两次内存,会报错,也就是说只要在类中有使用
系统统资源时,不能使用浅拷贝构造函数。浅赋值操作也有同样的问题。
当我们使用系统资源时,如何避免这种情况?只能重写拷贝构造函数和赋值操作。
重写浅拷贝构造函数,实现深拷贝。
Test(const Test& t) //深拷贝
{
mptr = new int;
*mptr = *(t.mptr);
i = t.j;
}
Test& operator= (const Test& t) //深赋值
{
if(this != &t) // 不能自赋值
{
delete mptr; //在操作类数组时,更方便设置大小,重新申请
mptr = new int;
i = t.j;
*mptr = *(t.mptr);
}
return *this; //确保可以连续赋值
}