深拷贝与浅拷贝
1、浅拷贝
浅拷贝,为值拷贝(在栈中把值拷贝给另一个变量),当变量为指针时,只是把地址拷贝过来,造成了多个指针指向同一块堆内存,在释放内存时会出现运行异常。
实例代码如 1 #define _CRT_SECURE_NO_WARNING 2 #include <iostream> 3 #include<cstdlib> 4
5 using namespace std; 6 7 class Teacher { 8 public: 9 Teacher(int id, char *name) { 10 cout << "Teacher(int,char*)..." << endl; 11 m_id = id; 12 int len = strlen(name); 13 m_name = (char*)malloc(len + 1);//因为这是C语言函数,它会在结尾增加\0,所以要加一个字节 14 //C语言中'\0'为转义字符,为字符串结束标志。 15 strcpy(m_name, name); 16 } 17 void print_t() { 18 cout << "id=" << m_id << ",name=" << m_name << endl; 19 } 20 //显示的提供一个拷贝构造函数 21 Teacher(const Teacher &another) { 22 m_id = another.m_id; 23 m_name = another.m_name;//此为浅拷贝,为值拷贝(在栈中把值拷贝给另一个变量),当变量为指针时,只是把地址拷贝过来。
} 28 29 ~Teacher() { 30 cout << "~Teacher()" << endl; 31 if (m_name != NULL) { 32 free(m_name); 33 m_name = NULL; 34 } 35 } 36 private: 37 int m_id; 38 char *m_name; 39 }; 40 41 void test() { 42 Teacher t1(1, "zhang3"); 43 t1.print_t(); 44 45 Teacher t2(t1);//调用t2的默认拷贝构造函数 46 t2.print_t(); 47 } 48 int main(void) { 49 test(); 51 system("pause"); 52 return 0; 53 }
上面代码运行会报错,原因是,浅拷贝中t2的char *name与t1的指向同一个堆中地址,(后构造的先析构)当t2调用完毕后会调用析构函数销毁堆中内存占用(name=NULL);
然后在t1调用析构函数时,name指向的空间已经释放,所以运行报错。
2、深拷贝
重新开辟内存空间,把上代码中的拷贝构造函数修改如下:
1 //显示的提供一个拷贝构造函数,来完成深拷贝动作(定义一个深拷贝) 2 Teacher(const Teacher &another) { 3 m_id = another.m_id; 4 //m_name = another.m_name;//此为浅拷贝 5 int len = strlen(another.m_name); 6 m_name = (char*)malloc(len + 1); 7 strcpy(m_name, another.m_name); 8 }
深拷贝为t2的name在堆中开辟了新的空间,在调用各自析构函数时各自释放各自的空间,代码正常运行。