C++ 浅拷贝和深拷贝

拷贝构造函数默认的是浅拷贝。当不涉及到堆内存时用浅拷贝完全可以,否则就需要深拷贝了。

浅拷贝相当于一个箱子有多个钥匙,但其中一个人打开箱子取走箱子里的东西时,其他人是不知道的。

深拷贝是有多个箱子每个箱子对应一个钥匙,但一个人取走他的钥匙对应的箱子里的东西时,不会对其他人产生影响。

 

 1 #include <bits/stdc++.h>
 2 
 3 using namespace std;
 4 
 5 class A{
 6 public:
 7     A() {
 8         cnt1++;
 9         name = new char(20);
10         strcpy(name, "hello");
11         cout << "A" << name << endl;
12     }
13     ~A() {
14         cnt2++;
15         cout << "~A" << name << endl;
16         delete name;
17         name = nullptr;
18     }
19     char *name;
20     static int cnt1;
21     static int cnt2;
22 };
23 
24 int A::cnt1 = 0;
25 int A::cnt2 = 0;
26 int main() {
27 
28     {
29         A a;
30         A b(a);
31     }
32 
33     cout << A::cnt1 << ' ' << A::cnt2 << endl;
34     return 0;
35 }

运行结果如下:

很明显对象b的name是一个空指针了,如果对空指针进行操作的话就会出现问题了。

所以涉及到堆内存时就需要自己实现拷贝构造函数了。

 

 1 #include <bits/stdc++.h>
 2 
 3 using namespace std;
 4 
 5 class A{
 6 public:
 7     A() {
 8         cnt1++;
 9         name = new char(20);
10         memmove(name, "hello", strlen("hello"));
11         cout << "A" << name << endl;
12     }
13     A(const A&b) {
14         name = new char(strlen(b.name)+1);
15         memmove(name, b.name, strlen(b.name));
16     }
17     ~A() {
18         cnt2++;
19         cout << "~A" << name << endl;
20         delete name;
21         name = nullptr;
22     }
23     char *name;
24     static int cnt1;
25     static int cnt2;
26 };
27 
28 int A::cnt1 = 0;
29 int A::cnt2 = 0;
30 int main() {
31 
32     {
33         A a;
34         A b(a);
35     }
36 
37     return 0;
38 }

运行结果如下:

 

随便讨论下vector。

vector可以看成一个可变大小的数组,有两个属性size和capacity,分别是大小和容量。大小表示当前元素的数量,而容量是表示当前能容量的元素数量。

当push_back()时,如果size和capacity相同时,首先向内存申请capacity*2(这个基数一般在1.5~2.0之间)大小的内存。然后将当前的元素拷贝到新的内存中,在释放原来的内存。

这样如果vector的类型没有自己实现拷贝构造函数时,默认是浅拷贝,比如下面这样就会出现问题。

 1 #include <bits/stdc++.h>
 2 
 3 using namespace std;
 4 
 5 class A{
 6 public:
 7     A() {
 8         cnt1++;
 9         name = new char(20);
10         strcpy(name, "hello");
11         cout << "A" << name << endl;
12     }
13     ~A() {
14         cnt2++;
15         cout << "~A" << name << endl;
16         delete name;
17         name = nullptr;
18     }
19     char *name;
20     static int cnt1;
21     static int cnt2;
22 };
23 
24 int A::cnt1 = 0;
25 int A::cnt2 = 0;
26 int main() {
27     {
28         vector<A> vs;
29         for(int i = 0; i < 4; i ++) {
30             A a;
31             vs.push_back(a);
32             cout <<"size:"<< vs.size() << ' ' <<  vs.capacity() << endl << endl;
33         }
34     }
35     cout << A::cnt1 << ' ' << A::cnt2 << endl;
36     return 0;
37 }

 

结果如下:

明显出现了问题,就如提示所言,产生了两次释放。

 

如果自己实现了拷贝构造函数就不同了。

 1 #include <bits/stdc++.h>
 2 
 3 using namespace std;
 4 
 5 class A{
 6 public:
 7     A() {
 8         cnt1++;
 9         name = new char(20);
10         strcpy(name, "hello");
11         cout << "A" << name << endl;
12     }
13     A(const A&b) {
14         name = new char(strlen(b.name)+1);
15         strcpy(name, b.name);
16     }
17     ~A() {
18         cnt2++;
19         cout << "~A" << name << endl;
20         delete name;
21         name = nullptr;
22     }
23     char *name;
24     static int cnt1;
25     static int cnt2;
26 };
27 
28 int A::cnt1 = 0;
29 int A::cnt2 = 0;
30 int main() {
31     {
32         vector<A> vs;
33         for(int i = 0; i < 4; i ++) {
34             A a;
35             vs.push_back(a);
36             cout <<"size:"<< vs.size() << ' ' <<  vs.capacity() << endl << endl;
37         }
38     }
39     cout << A::cnt1 << ' ' << A::cnt2 << endl;
40     return 0;
41 }

运行结果如下:

 

posted @ 2019-05-09 22:38  starry_sky  阅读(6744)  评论(0编辑  收藏  举报