不好馴服的析構函式

2021-05-22 20:54:24 字數 2771 閱讀 5339

首先看乙個深拷貝的例子

view plaincopy to clipboardprint?

01.#include

02.using namespace std;  

03.const int size          = 9;  

04.const int default_num   = 6;  

05.class a  

06.;  

20. 

21.a::a()  

22.  

26. 

27.a::~a()  

28.  

33. 

34.a::a(a &right)  

35.  

41. 

42.void a::set()//設定a的各個元素的值  

43.;

a::a()

a::~a()

a::a(a &right)

void a::set()//設定a的各個元素的值

int a::getsize()

int main()

可能我寫的有點亂,成員變數包括乙個指標,其實是乙個陣列,想要深拷貝。

所以我們需要過載拷貝建構函式。

初學c++的時候,直接記住了引數是引用型別,當時對語言沒有深入的理解(雖然現在也不深入),也就沒有往心裡去,這些天模擬stl,遇到了好多關於深拷貝的問題,而且這問題出的很怪異(我會在下午提出),因此想到了拷貝建構函式,所以在這裡需要深究一下。

拷貝建構函式的引數是引用型別。

我們可以試想一下不是引用的情況,也就是說,拷貝建構函式是下邊這個樣子:

view plaincopy to clipboardprint?

01.a::a(a right)  

02. 

a::a(a right)

引數傳遞的是乙個物件,按值傳遞,那麼這個物件就會被複製到right,複製的時候又會呼叫拷貝建構函式,那又會複製乙個物件到第二次呼叫的這個拷貝建構函式裡邊,因此又需要第三次呼叫拷貝建構函式。。。想一下,是不是無限迴圈?

簡單地說:傳值需要呼叫拷貝建構函式,而不是引用型別的拷貝建構函式又需要呼叫拷貝建構函式。因此無限迴圈。

ok,把引用的這個問題說明白,下邊說一下我這幾天遇到的這個問題:

請先看一段**:

view plaincopy to clipboardprint?

01.#include

02.#include

03.using namespace std;  

04. 

05.class a  

06.  

30.      

31.;  

32.};  

33.void a::setsize(int newsize)  

34.  

37. 

38.void a::setp(int *newp)  

39.  

42. 

43.void a::show()  

44.;

};void a::setsize(int newsize)

void a::setp(int *newp)

void a::show()

int a::getsize() const

a::a()

void a::fun()

size = 9;

}//關鍵是下邊的析構函式,如果進行delete操作,該程式就會出錯

a::~a()

int main()

可以試著執行一下,在我電腦上邊出現了下邊這個錯誤

很恐怖的錯誤。呵呵,讓我們詳細分析一下。

第一次a.show()成功,說明物件a建立沒有問題;b.show()失敗,說明沒有複製成功;第二次a.show()失敗,說明a被修改了,可以猜想一下,是不是被呼叫了析構函式?

現在過載 = 的時候是按值傳遞,那麼,我們傳進去的是位址p和size。

之後是執行拷貝的函式,這個沒啥問題,把right中的相關資料拷貝。

然後就開始執行析構函式了,首先析構的是傳進來的引數,也就是right,由於right的p和主函式中a的p相等,因此right的p被delete了也就是a的p被delete了,在這裡,我們把主函式中的a不小心析構了一點點(把p給delete了)。因為函式的返回的是值,所以第二步析構的是(*this),這樣,就把複製後的p給delete了。到這裡,我們悲劇地把記憶體中所有的p都delete了。

所以,當再次輸出a和b的時候,全都是隨機值。

細心的朋友可能會發現,當第二次輸出a和b的時候仍然是輸出了10個,也就是開始的size值。a的size是10不難理解。由於析構函式是在函式返回後呼叫的,所以返回的b的size是不改變的(返回是在改變以前)。

我們試著改一下:

下邊是我在引數上邊加了&,這樣,當再次輸出a的時候沒有錯誤

view plaincopy to clipboardprint?

01.a operator = (a &right) //過載的等號  

02. 

a operator = (a &right) //過載的等號

下邊是在引數right和返回值都加了&,這樣就沒有錯誤了。

view plaincopy to clipboardprint?

01.a &operator = (a &right)    //過載的等號  

02. 

a &operator = (a &right) //過載的等號

正好符合我們的分析。

不好馴服的析構函式

不好馴服的析構函式 本文假定您對 很願意和您交朋友 xiaobo68688 qq.com。注 想問我是學c 還是c 的朋友就不要發郵件了,謝謝!首先看乙個深拷貝的例子 可能我寫的有點亂 成員變數包括乙個指標,其實是乙個陣列,想要深拷貝。所以我們需要過載拷貝建構函式。初學c 的時候,直接記住了引數是引...

C 析構函式 虛析構函式

1.為什麼要定義虛析構函式?如果有乙個帶有虛函式功能的類,則它需要乙個虛析構函式,原因如下 1 如果乙個類有虛函式功能,它經常作為乙個基類使用 2 如果它是乙個基類,它的派生類經常使用new來分配 3 如果乙個派生類物件使用new來分配,並且通過乙個指向它的基類的指標來控制,那麼它經常通過乙個指向它...

建構函式 析構函式 虛析構函式

說析構函式之前,先說下建構函式。建構函式用來完成對物件的一系列初始化操作,主要作用有 1.給建立的物件建立乙個識別符號 2.為物件資料成員開闢記憶體空間 3.完成物件資料成員的初始化 當並未顯示的定義建構函式時,會生成乙個預設的建構函式,預設建構函式不能完成物件資料成員的初始化,只能給物件建立一識別...