首先看乙個深拷貝的例子
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.完成物件資料成員的初始化 當並未顯示的定義建構函式時,會生成乙個預設的建構函式,預設建構函式不能完成物件資料成員的初始化,只能給物件建立一識別...