出现深拷贝浅拷贝问题的原因先提前说明:
一个类或结构体中有指针,由于一个类或者结构体拷贝另外一个类或者结构体,使用了 Peroson p1 = p2; 或者 p1 = p2; 使用了系统默认的拷贝构造函数和等号操作符,这两个方法是使用的值拷贝,将两个对象的指针都指向了一块空间,一个对象释放空间后,另外一个对象再次释放,会导致程序崩掉
看不懂没关系,接下来我用几个例子来解释
class Person { public: //析构函数来释放内存 ~Person() { if(name != NULL) { free(name); } name = NULL; } public: char *name; int age; }; void Test() { Person p1; p1.name = (char *)malloc(100); strcpy(p1.name, "吴彦祖"); p1.age = 35; //调用拷贝构造函数 Person p2 = p1; //调用=操作符 Person p3; p3 = p1; } int main() { Test(); return 0; }
这就出现了我上述的问题,重复释放内存
毫无疑问,程序挂掉了,我们怎么来解决呢
如果你看懂了上面拷贝产生的原因,一定会知道,只需要把新拷贝的对象的指针重新分配内存即可
下面是代码
class Person { public: Person() {} //析构函数来释放内存 ~Person() { if(name != NULL) { free(name); } name = NULL; } Person(const Person& p) { //一定要加1 因为strlen不计算最后的'\0' 但是strcpy会在最后一位自动加上'\0' int len = strlen(p.name)+1; name = (char *)malloc(len); strcpy(name, p.name); age = p.age; } Person& operator=(const Person &p) { //切记 !! 一定先将原来的内存释放掉 if(name != NULL) { free(name); } //一定要加1 因为strlen不计算最后的'\0' 但是strcpy会在最后一位自动加上'\0' int len = strlen(p.name)+1; name = (char *)malloc(len); strcpy(name, p.name); age = p.age; return *this; } public: char *name; int age; }; void Test() { Person p1; p1.name = (char *)malloc(100); strcpy(p1.name, "吴彦祖"); p1.age = 35; //调用拷贝构造函数 Person p2 = p1; //调用=操作符 Person p3; p3 = p1; cout << "p1.name:" << p1.name << endl; cout << "p2.name:" << p2.name << endl; cout << "p3.name:" << p3.name << endl; } int main() { Test(); return 0; }
这样就不会挂掉了。
我第一种示范代码就是使用的浅拷贝,如果有内存分配释放则会挂掉
第二种示范是深拷贝
如果是c语言的结构体,可以自己定义一个函数来拷贝结构体,道理都是一样的
OK 结束