1. 程式人生 > >為什麼拷貝建構函式必須為引用傳遞,不能是值傳遞?

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

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

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

我們先看一下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回答了為什麼拷貝建構函式使用值傳遞會產生無限遞迴呼叫的問題;