深拷贝(Deep copy)和浅拷贝(Shallow copy)是指对于类或结构体这类复合类型的变量,当它们的成员变量中含有指针时,在赋值或初始化的过程中,如果只是修改指针的指向,则属于浅拷贝(也称位拷贝)。因为此时指针所指向的实际内容依然只有一份,当其中一个变量销毁时,则该内存将被释放,那么此时另一个变量中将存在悬挂指针。而如果在发生拷贝时首先将需要被拷贝的内容复制到一个新的内存地址,然后再将相应的指针指向该新地址,则称为深拷贝。SOF上的一个相关回答http://stackoverflow.com/questions/184710/what-is-the-difference-between-a-deep-copy-and-a-shallow-copy <>
首先提示:在C++中,对于类型class1来说,class1 a(b);等价于class1 a = b;都将调用拷贝构造函数进行初始化,而不是将后面的语句中使用赋值运算符对a进行赋值。如果要使用赋值运算符将b赋值给a,需要class1 a; a = b;
下面举例说明:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 #include <iostream> #include <cstring> class A {public : A () = delete ; A (const char *str); A (const A &other); A (const A &other, bool unuse); A& operator =(const A& other); ~A (); private : char *name; bool unused; }; A::A (const A &other) { std::cout << "浅拷贝的拷贝构造函数" << std::endl; name = other.name; } A::A (const A &other, bool unuse) { std::cout << "深拷贝的拷贝构造函数" << std::endl; name = new char [strlen (other.name) + 1 ]; strcpy (name, other.name); unused = unuse; } A::A (const char *str) { std::cout << "深拷贝的构造函数" << std::endl; if (str != nullptr ) { name = new char [strlen (str) + 1 ]; std::strcpy (name, str); } else { name = new char [1 ]; name[0 ] = '\0' ; } } A& A::operator =(const A& other) { std::cout << "深拷贝的赋值运算符" << std::endl; if (this != &other) { A to (other, true ) ; char *tn = name; name = to.name; to.name = tn; } return *this ; } A::~A () { std::cout << "析构函数" << std::endl; delete [] name; } int main (void ) { char ts[] = "I love China" ; A a (ts) ; A d (ts) ; d = a; return 0 ; }
输出结果为:
1 2 3 4 5 6 7 深拷贝的构造函数 深拷贝的构造函数 深拷贝的赋值运算符 深拷贝的拷贝构造函数 析构函数 析构函数 析构函数
如果使用浅拷贝,也就是取消注释A c = a;
输出结果为:
1 2 3 4 5 6 7 8 9 10 11 12 深拷贝的构造函数 浅拷贝的拷贝构造函数 深拷贝的构造函数 深拷贝的赋值运算符 深拷贝的拷贝构造函数 析构函数 析构函数 析构函数 析构函数 *** Error in `./copy_deep_shallow': double free or corruption (fasttop): 0x0000000002595010 *** Command terminated
由此可见深拷贝会拷贝动态分配的成员对象,而不仅仅是简单的指针赋值 深拷贝只拷贝非静态成员数据,因为类的静态成员被类及所有类对象共有一份