赋值运算符重载
c++默认提供的四种函数:默认构造,析构,拷贝构造(值拷贝),operator=(值拷贝)
深浅拷贝的问题一般出现在类中有属性是要开辟在堆区的,并且析构函数中写了释放堆区内存的代码,那么要注意不要对堆区内存进行重复释放的操作
1.深浅拷贝的问题
operator=编译器提供的浅拷贝操作
//赋值运算符重载(赋值拷贝)
wood& operator=(wood& w1) //w1是要进行拷贝的值
{
//浅拷贝
num = w.num;
}
自己改写为深拷贝的操作
注意:如果是深拷贝赋值,那么在赋值拷贝之前,被赋值的对象可能已经在堆区开辟了内存,所以要先释放在堆区开辟的内存
#include<iostream>
using namespace std;
class wood {
public:
wood(int num) {
this->num = new int(num);
cout << "构造函数调用" << endl;
}
//赋值运算符重载(赋值拷贝)
wood& operator=(wood& w1) //w1是要进行拷贝的值
{
//浅拷贝
//num = w.num;
//深拷贝
//防止自赋值
if (this != &w1)
{
//如果本身已经在堆区开辟内存,就先释放
if (num != NULL)
{
delete num;
num = NULL;
}
num = new int(*w1.num);
return *this;
}
}
//析构函数
~wood() {
if (num != NULL)
{
delete num;
num = NULL;
}
cout << "析构函数调用" << endl;
}
int* num;
};
void test()
{
wood w(10);
cout << *w.num << endl;
wood w1(20);
w1 = w;
cout << *w1.num << endl; //在析构函数里面写了delete语句释放内存后,就会造成内存的重复释放,需要进行深拷贝操作
}
int main()
{
test();
return 0;
}
默认拷贝构造(浅拷贝)
改造为深拷贝
进行深拷贝的时候,不需要判断被赋值的对象是否在堆区开辟了内存,因为这里相当于进行新创建对象的初始化操作,新对象还没有进行任何属性初始化操作,除非无参构造里面对新对象做了属性堆区开辟的操作
#include<iostream>
using namespace std;
class wood {
public:
wood(int num) {
this->num = new int(num);
cout << "构造函数调用" << endl;
}
wood(wood & w)
{
this->num = new int(*w.num);
}
//析构函数
~wood() {
if (num != NULL)
{
delete num;
num = NULL;
}
cout << "析构函数调用" << endl;
}
private:
int* num;
};
void test()
{
wood w1(10);
wood w = w1;//默认拷贝构造
}
int main()
{
test();
return 0;
}
注意:值拷贝过程中堆区内存被重复释放的问题
可用传引用的方式解决
#include<iostream>
using namespace std;
class wood {
friend ostream& operator<<(ostream& cout, wood wood);
public:
wood(int num) {
this->num = new int(num);
cout << "构造函数调用" << endl;
}
//析构函数
~wood() {
if (num != NULL)
{
delete num;
num = NULL;
}
cout << "析构函数调用" << endl;
}
private:
int* num;
};
//这里是值拷贝
ostream& operator<<(ostream& cout, wood wood)
{
cout << "木头的数量为:" << *wood.num << endl;
return cout;
}
void test()
{
wood w(10);
cout << w << endl;
//operator<<(cout, w);
}
int main()
{
test();
return 0;
}