在copy一个对象时(用一个对象去初始化另外一个对象),会调用类中的拷贝构造函数。如果我们自己没有在类里面写拷贝构造函数,则C++编译器会调用默认的拷贝构造函数。
浅拷贝:如果类定义的对象包含的某个成员是动态内存分配产生的(指针变量成员),你先用该类定义了一个对象1,然后又用这个对象1去初始化另外一个对象2。如果在类里面,没有自己写拷贝构造函数,C++编译器会调用默认的拷贝构造函数,只能将对象1的成员的值赋给对象2的成员,对象1成员指向的内存并没有被复制,也就是说对象1指针成员和对象2指针成员指向的是同一块内存。这样在析构对象时,先析构对象2,对象2指针成员指向的内存被free。由于对象1指针成员和对象2指针成员的值一样,指向的是同一块内存,析构对象1的指针成员时,它所指向的那块内存之前已经被对象2的指针成员free,没法再次free,就会出现宕机(down机),这就是浅拷贝问题。浅拷贝问题在编译阶段不会出问题,只有当程序运行的时候才会发现问题。
浅拷贝问题图解
如果要解决浅拷贝问题,那就必须深拷贝。所谓的深拷贝,就是说不仅将对象1的值拷贝给对象2,而且要将对象1指针成员指向的内存空间也要赋值一份给对象2。这时候,我们就不能再用C++编译器给我们提供的默认拷贝构造函数,必须自己写一份拷贝构造函数。
关于浅拷贝和深拷贝问题,可以参考以下代码:
1 //myname.h 2 #pragma once 3 class myname 4 { 5 public: 6 myname(const char*); 7 myname(const myname&); 8 ~myname(void); 9 void printN(); 10 11 private: 12 int len; 13 char* p; 14 }; 15 16 17 //myname.cpp 18 #include "myname.h" 19 #include "string.h" 20 #include "malloc.h" 21 #include <iostream> 22 23 #define _CRT_SECURE_NO_WARNINGS 24 25 //构造函数 26 myname::myname(const char* myp) 27 { 28 len=strlen(myp); 29 p=(char*)malloc(sizeof(char)*(len+1)); 30 strcpy(p,myp); 31 } 32 33 //拷贝构造函数。如果不自己写该函数,C++编译器会调用默认的拷贝构造函数,则会发生浅拷贝。自己写了该函数,C++编译器就会调用该函数,发生的是深拷贝 34 myname::myname(const myname& n) 35 { 36 len=n.len; 37 p=(char*)malloc(sizeof(char)*(len+1)); 38 strcpy(p,n.p); 39 } 40 41 42 void myname::printN() 43 { 44 std::cout<<"name:"<<p<<std::endl; 45 } 46 47 48 myname::~myname(void) 49 { 50 free(p); 51 p=NULL; 52 len=0; 53 } 54 55 56 //main函数 57 #include<iostream> 58 #include "myname.h" 59 60 using namespace std; 61 62 int main() 63 { 64 65 myname name1("Zhang wuji"); 66 myname name2(name1); 67 name2.printN(); 68 69 70 return 0; 71 }