C++ 类的深拷贝和浅拷贝完美解决
Posted 庖丁解牛
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了C++ 类的深拷贝和浅拷贝完美解决相关的知识,希望对你有一定的参考价值。
//类的深拷贝和浅拷贝 #define _CRT_SECURE_NO_WARNINGS #include<iostream> using namespace std; class Point{ public: Point(int _a,int _b,const char *pin/*in*/){ x = _a; y = _b; remark = (char *)malloc(sizeof(char)*(strlen(pin) + 1)); strcpy(remark, pin); cout << "我是自定义的有参构造函数4" << endl; } Point(Point &pm){ cout << "我是自定义的拷贝构造函数3" << endl; //修改拷贝构造函数 x = pm.x; y = pm.y; //remark = pm.remark; 这句话错误 //修改后的方案 remark = (char *)malloc(sizeof(char)*(strlen(pm.remark) + 1)); strcpy(remark, pm.remark); } ~Point(){ if (remark!=NULL) { free(remark); } cout << "我是自定义的析构函数2" << endl; } void GetPremark(){ printf("指针变量remark的地址是%x\\n", remark); } //BBB---运算符重载 void operator=(Point &pm){ //CCC 解决方案第三步 if (remark!=NULL) { free(remark); remark = NULL; } //解决方案改良第二步(以下) x = pm.x; y = pm.y; remark = (char *)malloc(sizeof(char)*(strlen(pm.remark) + 1)); strcpy(remark, pm.remark); } private: int x; int y; char *remark; }; void ProtectA(){ Point p1(1, 1, "123"); Point p2 = p1; printf("这是p1中字符指针的地址\\n"); p1.GetPremark();//打印 ad95e8 printf("这是p2中字符指针的地址\\n"); p2.GetPremark();//打印 ad95e8 //这说明类对象之间拷贝指针拷贝了指针变量的值(两个指针指向同一片内存),并没有新分配内存 //出现问题:当先调用p2(函数的压栈,先定义后释放)的析构函数的时候,会释放指针变量remark指向的内存, //当调用p1的析构函数的时候就会报错 //解决方案第一步--修改类的拷贝构造函数 //BUG事例 //Point p3;//报错 error C2512: “Point”: 没有合适的默认构造函数可用 //这说明只要定义了有参构造函数,那么c++编译器就不会自动创建无参构造函数 Point p4(2,3,"456"); //赋值操作 //p4 = p2; //分析:赋值操作会将p2的所有值(包括指针变量的值)拷贝到p4对象中 //此时又会出现两个指针变量指向同一片内存的情况,当析构对象p4的时候,会释放指针变量指向的内存 //那么析构p2的时候又会报错(那块内存已经被释放了,被释放了2次) //解决方案第二步--"="运算符重载 //详情见 BBB 运算符重载的使用场景 p4 = p2; //BUG事例 p4 = p1; //分析:当执行p4 = p2; p4 = p1;仔细分析"="重载函数发现,p4 = p2;p4会开辟一块内存N1, //p4 = p1;p4会再开辟一块内存N2,此时N1这块内存永远不会被释放,这就造成了内存泄漏 //为了解决这个问题 //解决方案第三步 //我们可以在执行"="重载函数之前判断一下指针变量指向的内存又没有释放, //(所以要确定--定义对象的时候必须要分配指针变量的内存或者将指针变量置空) ///详情见 CCC } void main(){ ProtectA(); system("pause"); }
以上是关于C++ 类的深拷贝和浅拷贝完美解决的主要内容,如果未能解决你的问题,请参考以下文章