浅拷贝会造成指针悬挂的问题。
举个例子:两个对象是s1和s2的指针_str都指向new开辟的同一块空间,如下图,主程序结束时,对象逐个撤销,先撤销对象s2,会调用析构函数释放动态分配的内存;再撤销对象s1时,s1._str所指向的内存空间已经是无法访问了,而s2._str原先指向的那块内存却无法释放,出现了所谓的指针悬挂! 两个对象企图释放同一块内存,从而导致一块内存被释放两次这也是不行的,运行会出错。
1 #include <iostream>浅拷贝
2 using namespace std;
3
4 class String
5 {
6 public:
7 String(char *str)
8 :_str(new char [strlen(str )+1])
9 {
10 strcpy(_str, str);
11 }
12 String(const String & s)
13 {
14 _str = s._str;
15 }
16 String& operator=(const String & s )
17 {
18 if (this !=&s)
19 {
20 _str = s._str;
21 }
22 return *this ;
23 }
24 ~String()
25 {
26 delete[] _str;
27 }
28 private:
29 char* _str;
30 };
31
32 void Test()
33 {
34 String s1("Lynn" );
35 String s2=s1;
36 }
37 int main()
38 {
39 Test();
40 system("pause" );
41 return 0;
42 }
深拷贝 深拷贝解决了指针悬挂的问题,当调用拷贝构造或赋值运算符的重载函数时,程序会生成一份该内存的拷贝,这样每个指针都会指向一块相对独立的空间,撤销对象时调用析构函数,分别释放他们自己的动态分配的内存,相互之间不影响。如下图:
深拷贝1 ///////////////////////////////////////////////////////////////////////////////////////
2
3 // 写String类的构造函数时一定要注意参数问题
4 // 首先要考虑到构造的对象分有参数和无参数两种情况
5 // 构造对象的时候不能直接赋值,否则一块内存两次释放的话程序会出错
6 // 无参的构造函数不能将_str指针赋值为NULL,因为不能strlen(NULL)
7 // 赋值运算符的重载要考虑到有可能分配内存失败的问题
8 // 当然,记得要给'\0'分配空间哦
9 // By:Lynn-Zhang
10 //////////////////////////*****************////////////////////////////////////////////
11
12 #include<iostream>
13 using namespace std;
14
15 class String
16 {
17 public:
18
19 String(char * str="") //不能strlen(NULL)
20 :_str(new char [strlen(str ) + 1])
21 {
22 strcpy(_str, str);
23 }
24 String(const String &s)
25 :_str(new char [strlen(s ._str) + 1])
26 {
27 strcpy(_str, s._str);
28 }
29
30 //赋值运算符的重载
31 String& operator=(const String& s)
32 {
33 if (this != &s )
34 {
35 /* //有可能开辟空间失败,但是却破坏了_str的内容
36 delete[] _str;
37 _str = new char[strlen(s._str) + 1];
38 strcpy(_str, s._str); */
39
40 char* tmp = new char [strlen(s ._str) + 1];
41 strcpy(tmp, s._str);
42 delete[] _str;
43 swap(_str, tmp);
44
45 }
46 return *this ;
47 }
48 char* CStr()
49 {
50 return _str;
51 }
52 ~String()
53 {
54 delete[] _str;
55 }
56 private:
57 char* _str;
58 };
59
60
61 //函数测试
62 void Test()
63 {
64 String s1("aaaaa" );
65 cout << s1.CStr() << endl;
66 String s2(s1);
67 cout << s2.CStr() << endl;
68 String s3 = s1;
69 s3= s2;
70 cout << s3.CStr() << endl;
71 String s4;
72 // s4 = s1;
73 cout << s4.CStr() << endl;
74
75 }
76 int main()
77 {
78 Test();
79 system("pause" );
80 return 0;
81 }