C 拷貝建構函式 深拷貝 淺拷貝

2021-07-13 22:33:18 字數 3040 閱讀 5619

基本概念:

深拷貝:

將乙個物件拷貝給另乙個物件的時候,被賦值的物件儲存賦值物件的乙個額外副本。若類成員中含有指標成員,且用new初始化的時候,被賦值的成員,會申請一塊記憶體,將賦值物件的指標成員所指的記憶體的內容複製到這塊記憶體中。兩個指標各自指向自己申請的記憶體

淺拷貝:

和深拷貝相似,淺拷貝對於非指標成員都是直接賦值。但是當類成員中含指標成員,且用new初始化的時候,被賦值的成員指標並不會額外申請一塊記憶體,而僅僅是將自己指向賦值物件的指標成員所指的那塊記憶體。兩個指標指向同一塊記憶體

。當我們沒有定義類的複製建構函式和賦值運算子時,編譯器會生成預設的版本,它們使用淺拷貝

回到上面所說的,為什麼我們需要定義"深拷貝"的複製建構函式和賦值運演算法捏 ? 難道,是因為預設的淺拷貝會導致錯誤 ?

沒錯!  我們知道,如果定義的類中含指標成員,如果它將會使用new申請新記憶體。在析構函式中,我們會用delete釋放相應的記憶體占用。

考慮兩種情況:

1. 乙個物件使用另外乙個已有物件初始化,這樣將呼叫預設複製建構函式(有可能還會呼叫賦值操作符,視編譯器而定)。由於使用淺拷貝,就會存在這兩個物件的指標成員指向同一塊記憶體的情況,當這兩個物件棄用時,會呼叫它們的析構函式。這樣會出現同一塊記憶體被釋放兩次的情況,出現未知的錯誤。

類似地,如果你定義了乙個返回物件的函式,也會造成同一塊記憶體釋放兩次的情況,為啥 ? 因為這還將呼叫複製建構函式,按值傳遞意味著建立原始變數的乙個副本。caller和這個函式(callee)中的物件的指標指向同一塊記憶體。當函式返回的時候,函式中的這個物件要被kill掉,呼叫析構函式了,釋放掉占用的記憶體... 放心,這些都不會告訴你的。嗯,當caller中的那個物件析構時,那塊記憶體又被釋放了一次... 仍然是不可預知的錯誤。類似地,建立臨時物件的時候,也會呼叫複製建構函式,這將發生同樣的趣事--同樣的奇怪的錯誤。

2.兩個已有物件之間的賦值,這將呼叫預設賦值運算子函式。後面的情況和1相同,都是淺拷貝鬧的--兩個物件的指標指向同一塊記憶體,然後被釋放兩次。

「當定義的類中含有指標成員,且使用常規new(或定位new,定位在申請的堆記憶體中)初始化的時候,需定義深拷貝的複製建構函式和賦值操作符」,不然會被外星人抓走。

圖示:

**示例:

c++ code

//淺拷貝  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

#include

#include

using

namespace std;

class person

~person()

};

int main()

c++ code 

//深拷貝 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

#include

#include

using

namespace std;

class person

;

person::person(

char *pn)

person::person(

const person &p)

person::~person()

void main()

C 拷貝建構函式 深拷貝,淺拷貝

對於普通型別的物件來說,它們之間的複製是很簡單的,例如 int a 88 int b a 而類物件與普通物件不同,類物件內部結構一般較為複雜,存在各種成員變數。下面看乙個類物件拷貝的簡單例子。執行程式,螢幕輸出100。從以上 的執行結果可以看出,系統為物件b分配了記憶體並完成了與物件a的複製過程。就...

C 拷貝建構函式 深拷貝,淺拷貝

對於普通型別的物件來說,它們之間的複製是很簡單的,例如 int a 88 int b a 而類物件與普通物件不同,類物件內部結構一般較為複雜,存在各種成員變數。下面看乙個類物件拷貝的簡單例子。include using namespace std class cexample void show 執...

C 拷貝建構函式 深拷貝,淺拷貝

c 拷貝建構函式 深拷貝,淺拷貝 對於普通型別的物件來說,它們之間的複製是很簡單的,例如 int a 88 int b a 而類物件與普通物件不同,類物件內部結構一般較為複雜,存在各種成員變數。下面看乙個類物件拷貝的簡單例子。iostream using namespace std class ce...