為什麼拷貝建構函式必須為引用傳遞,不能是值傳遞?

2021-06-20 17:25:36 字數 1322 閱讀 5249

對於拷貝建構函式引用傳遞,似乎司空見慣,認為理所當然。但是被問起這個問題,的確是一片茫然,為什麼呢?

去網上搜尋了一下,的確有很多這方面的知識講解。

我們先看一下csdn上的乙個帖子的回答:

簡單的回答是為了防止遞迴引用。

具體一些可以這麼講:

當 乙個物件需要以值方式傳遞時,編譯器會生成**呼叫它的拷貝建構函式以生成乙個複本。如果類a的拷貝建構函式是以值方式傳遞乙個類a物件作為引數的話,當 需要呼叫類a的拷貝建構函式時,需要以值方式傳進乙個a的物件作為實參; 而以值方式傳遞需要呼叫類a的拷貝建構函式;結果就是呼叫類a的拷貝建構函式導 致又一次呼叫類a的拷貝建構函式,這就是乙個無限遞迴。

這個解釋還是蠻具體的。

利用值傳遞的話,會導致遞迴引用。

還有一片文章也談到了這個問題, 我覺得寫得也非常好!

其中講到了3個問題

1是拷貝建構函式的作用。

作用就是用來複製物件的,在使用這個物件的例項來初始化這個物件的乙個新的例項。

2是引數傳遞過程到底發生了什麼?

將位址傳遞和值傳遞統一起來,歸根結底還是傳遞的是"值"(位址也是值,只不過通過它可以找到另乙個值)!

i)值傳遞:

對於內建資料型別的傳遞時,直接賦值拷貝給形參(注意形參是函式內區域性變數);

對於類型別的傳遞時,需要首先呼叫該類的拷貝建構函式來初始化形參(區域性物件);如void foo(class_type obj_local){}, 如果呼叫foo(obj);  首先class_type obj_local(obj) ,這樣就定義了區域性變數obj_local供函式內部使用

ii)引用傳遞:

無論對內建型別還是類型別,傳遞引用或指標最終都是傳遞的位址值!而位址總是指標型別(屬於簡單型別), 顯然引數傳遞時,按簡單型別的賦值拷貝,而不會有拷貝建構函式的呼叫(對於類型別).

3是在類中有指標資料成員時,拷貝建構函式的使用?

如果不顯式宣告拷貝建構函式的時候,編譯器也會生成乙個預設的拷貝建構函式,而且在一般的情況下執行的也很好。但是在遇到類有指標資料成員時就出現問題 了:因為預設的拷貝建構函式是按成員拷貝構造,這導致了兩個不同的指標(如ptr1=ptr2)指向了相同的記憶體。當乙個例項銷毀時,呼叫析構函式 free(ptr1)釋放了這段記憶體,那麼剩下的乙個例項的指標ptr2就無效了,在被銷毀的時候free(ptr2)就會出現錯誤了, 這相當於重複釋放一塊記憶體兩次。這種情況必須顯式宣告並實現自己的拷貝建構函式,來為新的例項的指標分配新的記憶體。

問題1和2回答了為什麼拷貝建構函式使用值傳遞會產生無限遞迴呼叫的問題;

問題3回答了回答了在類中有指標資料成員時,拷貝建構函式使用值傳遞等於白顯式定義了拷貝建構函式,因為預設的拷貝建構函式就是這麼幹的。

為什麼拷貝建構函式必須為引用傳遞,不能是值傳遞?

拷貝建構函式的標準寫法如下 class base base const base b 上述寫法見得最多,甚至你認為理所當然。那麼如果我們不寫成引用傳遞呢,而是值傳遞,那麼會怎樣?class base base const base b 編譯出錯 error c2652 base illegal co...

為什麼拷貝建構函式必須為引用傳遞,不能是值傳遞?

拷貝建構函式的標準寫法如下 class base base const base b 上述寫法見得最多,甚至你認為理所當然。那麼如果我們不寫成引用傳遞呢,而是值傳遞,那麼會怎樣?class base base const base b 編譯出錯 error c2652 base illegal co...

拷貝建構函式為什麼要用引用傳參?

拷貝建構函式是類的六個預設成員函式之一,他是建構函式的乙個過載形式,其引數只有乙個且必須要引用傳遞,那我們不禁想問值傳遞可以嘛?下面是乙個拷貝建構函式的 讓我們來分析下 date const date d intmain 當用已存在的物件建立新物件時候,編譯器會自動呼叫拷貝建構函式完成新物件的初始化...