对象的深拷贝和浅拷贝

时间:2023-01-05 19:49:57

在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 }