利用深拷贝的方法解决浅拷贝的问题,代码如下:
#include<iostream>
using namespace std;
#include<string>
class father
{
public:
father()
{
cout << "father函数的无参构造函数" << endl;
}
father(int a, string name)
{
M_age = a;
M_name = new string(name);//用指针去接收地址
cout << "father函数的有参构造函数" << endl;
}
father(const father& f)
{
M_age = f.M_age;//拷贝构造函数可写的写法,
//M_name = f.M_name;//系统默认写法,浅拷贝,会引起代码运行中断,浅拷贝问题,重复释放堆区内存
M_name = new string(*f.M_name);//深拷贝写法,重新开辟空间,防止内存重复释放
cout << "father函数的拷贝构造函数" << endl;
}
//浅拷贝的时候代码可以不写,编译器会自己提供,但是要解决浅拷贝问题的时候,深拷贝代码一定要写
//析构代码的作用是释放开辟在堆区的空间
~father()
{
if (M_name != NULL)
{
delete M_name;
M_name = NULL;
}
cout << "father析构函数的调用" << endl;
}
int M_age;
string* M_name;
};
void func()
{
father f(10,"jing");
cout << *f.M_name <<":" << f.M_age << endl;
father f2(f);
cout << *f2.M_name<< ":" << f2.M_age << endl;
}
int main()
{
func();
system("pause");
return 0;
}
浅拷贝代码:
father(const father &f)
{
M_age=f.M_age;
M_name=f.M_name;
}
以上代码出现的问题就是在系统销毁空间的时候,系统会重复清理堆区的代码,也就是我们上面写的有参构造开辟出来的堆区。由于我们后面写的对象就是father f(10,"jing");
和father f2(f);
都是局部对象,开辟在栈区,而栈的特点是先进后出,所以f2会被先释放掉,其次再去释放f1,但是f2是拷贝f1的,所以在释放f2的时候,开辟的堆区空间就已经被释放掉了,而f1又走了一遍析构代码,重复释放,所以浅拷贝代码会崩,而深拷贝就是解决浅拷贝问题的。
深拷贝解决问题的逻辑就是在拷贝的时候自己申请一块内存空间,这样就不会重复释放了,但是拷贝过后的内容一样,从而解决浅拷贝的问题。