拷貝建構函式的標準寫法如下:
class base
base(const base &b)
//}
上述寫法見得最多,甚至你認為理所當然。
那麼如果我們不寫成引用傳遞呢,而是值傳遞,那麼會怎樣?
class base
base(const base b){}
//}
編譯出錯:error c2652: 'base' : illegal copy constructor: first parameter must not be a 'base'
事實上,你可以從這個小小的問題認真搞清楚2件事:
1) 拷貝建構函式的作用就是用來複製物件的,在使用這個物件的例項來初始化這個物件的乙個新的例項。其實,個人認為不應該叫這些constructor(default constructor, copy constructor....)為建構函式,更佳的名字應該是"初始化函式"
2) 引數傳遞過程到底發生了什麼?
將位址傳遞和值傳遞統一起來,歸根結底還是傳遞的是"值"(位址也是值,只不過通過它可以找到另乙個值)!
i)值傳遞:
對於內建資料型別的傳遞時,直接賦值拷貝給形參(注意形參是函式內區域性變數);
對於類型別的傳遞時,需要首先呼叫該類的拷貝建構函式來初始化形參(區域性物件);如void foo(class_type obj_local){}, 如果呼叫foo(obj); 首先class_type obj_local(obj) ,這樣就定義了區域性變數obj_local供函式內部使用
ii)引用傳遞:
無論對內建型別還是類型別,傳遞引用或指標最終都是傳遞的位址值!而位址總是指標型別(屬於簡單型別), 顯然引數傳遞時,按簡單型別的賦值拷貝,而不會有拷貝建構函式的呼叫(對於類型別).
上述1) 2)回答了為什麼拷貝建構函式使用值傳遞會產生無限遞迴呼叫...
3). 如果不顯式宣告拷貝建構函式的時候,編譯器也會生成乙個預設的拷貝建構函式,而且在一般的情況下執行的也很好。但是在遇到類有指標資料成員時就出現問題了:因為預設的拷貝建構函式是按成員拷貝構造,這導致了兩個不同的指標(如ptr1=ptr2)指向了相同的記憶體。當乙個例項銷毀時,呼叫析構函式free(ptr1)釋放了這段記憶體,那麼剩下的乙個例項的指標ptr2就無效了,在被銷毀的時候free(ptr2)就會出現錯誤了, 這相當於重複釋放一塊記憶體兩次。這種情況必須顯式宣告並實現自己的拷貝建構函式,來為新的例項的指標分配新的記憶體。
上述3)回答了在類中有指標資料成員時,拷貝建構函式使用值傳遞等於白顯式定義了拷貝建構函式,因為預設的拷貝建構函式就是這麼幹的...
為什麼拷貝建構函式必須為引用傳遞,不能是值傳遞?
拷貝建構函式的標準寫法如下 class base base const base b 上述寫法見得最多,甚至你認為理所當然。那麼如果我們不寫成引用傳遞呢,而是值傳遞,那麼會怎樣?class base base const base b 編譯出錯 error c2652 base illegal co...
為什麼拷貝建構函式必須為引用傳遞,不能是值傳遞?
對於拷貝建構函式引用傳遞,似乎司空見慣,認為理所當然。但是被問起這個問題,的確是一片茫然,為什麼呢?去網上搜尋了一下,的確有很多這方面的知識講解。我們先看一下csdn上的乙個帖子的回答 簡單的回答是為了防止遞迴引用。具體一些可以這麼講 當 乙個物件需要以值方式傳遞時,編譯器會生成 呼叫它的拷貝建構函...
拷貝建構函式為什麼要用引用傳參?
拷貝建構函式是類的六個預設成員函式之一,他是建構函式的乙個過載形式,其引數只有乙個且必須要引用傳遞,那我們不禁想問值傳遞可以嘛?下面是乙個拷貝建構函式的 讓我們來分析下 date const date d intmain 當用已存在的物件建立新物件時候,編譯器會自動呼叫拷貝建構函式完成新物件的初始化...