標籤:ons 傳遞 拷貝賦值運算子 數組 span 接受 運算 無限迴圈 元素
拷貝建構函式
如果一個建構函式的第一個參數是自身類類型的引用,且任何額外參數都有預設值,則此建構函式是拷貝建構函式。
拷貝建構函式第一個參數必須是一個參考型別。此參數幾乎總是一個const的引用。拷貝建構函式在幾種情況下都會被隱式地使用。因此,拷貝建構函式通常不應該是explicit的。
合成拷貝建構函式
與合成預設建構函式不同,即使我們定義了其他建構函式,編譯器也會為我們合成一個拷貝建構函式。
對某些類來說,合成拷貝建構函式用來阻止我們拷貝該類類型的對象。而一般情況,合成的拷貝建構函式會將其參數的成員逐個拷貝到正在建立的對象中。每個成員的類型決定了它如何拷貝。
拷貝初始化
直接初始化和拷貝初始化的差異。
string dots(10,‘,‘); //直接初始化
string s(dots); //直接初始化
string s2 = dots; //拷貝初始化
當使用直接初始化時,我們實際上是要求編譯器使用普通的函數匹配來選擇與我們提供的參數最匹配的建構函式。當我們使用拷貝初始化時,我們要求編譯器將右側運算對象拷貝到正在建立的對象中,如果需要的話還要進行類型轉換。
拷貝初始化通常使用拷貝建構函式來完成。拷貝初始化是依靠拷貝建構函式或移動建構函式來完成的。
拷貝初始化不僅在我們用=定義變數時會發生,在下列情況下也會發生
?將一個對象作為實參傳遞給一個非參考型別的形參。
?從一個傳回型別為非參考型別的函數返回一個對象。
?用花括弧列表初始化一個數組中的元素或一個彙總類中的成員。
參數和傳回值
拷貝建構函式被用來初始化非引用類型別參數,這一特性解釋了為什麼拷貝建構函式自己的參數必須是參考型別。如果其參數不是參考型別,則調用永遠也不會成功——為了調用拷貝建構函式,我們必須拷貝它的實參,但為了拷貝實參,我們又必須調用拷貝建構函式,如此無限迴圈。
拷貝初始化的限制
vector<int> v1(10); //直接初始化
vector<int> v1 = 10; //錯誤:接受大小參數的建構函式是explicit的
如果我們希望使用一個explicit建構函式,就必須顯式的使用:
void f(vector<int>); //f的參數進行拷貝初始化
f(10); //錯誤:不能用一個explicit的建構函式拷貝一個實參
f(vector<int>(10)); //正確:從一個int直接構造一個臨時vector
如果我們希望使用一個explicit建構函式,就必須顯式的使用:
編譯器可以繞過拷貝建構函式
編譯器被允許將下面的代碼string null_book = "9-999-99999-9";
給寫成string null_book("9-999-99999-9");//編譯器略過了拷貝建構函式。
拷貝賦值運算子
類通過拷貝賦值運算子控制其對象如何賦值。
重載賦值運算子
重載賦值運算子本質上是函數,其名字由operator關鍵字後接表示要定義的運算子的符號組成。因此,賦值運算子就是一個名為operator=的函數。類似於任何其他函數,運算子函數也有一個傳回型別和一個參數列表。
值得注意的是,標準庫通常要求儲存在容器中的類型要具有賦值運算子,且其傳回值是左側運算對象的引用。
合成拷貝賦值運算子
與處理拷貝建構函式一樣,如果一個類未定義自己的拷貝賦值運算子,編譯器會為他它產生一個合成拷貝賦值運算子。類似拷貝建構函式,對於某些類,合成拷貝構造運算子用來禁止該類型對象的賦值。
解構函式
三/五法則
使用=default
阻止拷貝
c++類的拷貝、賦值與銷毀(拷貝建構函式、拷貝賦值運算子解構函式)