1. 程式人生 > >C++Primer_Chap13_拷貝控制_筆記

C++Primer_Chap13_拷貝控制_筆記

一個類可以通過定義五種特殊的成員函式來控制此型別的物件拷貝、移動、賦值和銷燬時的具體實現:

  1. 拷貝建構函式(copy constructor)
  2. 拷貝賦值運算子(copy-assignment operator)
  3. 移動建構函式(move constructor)
  4. 移動賦值運算子(move-assignment operator)
  5. 解構函式(destructor)

拷貝建構函式

  如果一個建構函式的第一個引數自身類型別的引用(如果不是引用,在傳遞引數時會呼叫拷貝建構函式即本身),且額外任何引數都有預設值,此建構函式為拷貝建構函式。如果我們沒有為一個類定義拷貝建構函式,編譯器會為我們定義一個。與合成預設建構函式不同,即使我們定義了其他建構函式,編譯器也會為我們合成一個拷貝建構函式。對於某些類,合成拷貝建構函式用來禁止該型別物件的拷貝。

  拷貝初始化通常使用拷貝建構函式來完成,但也會使用移動建構函式來完成。

  拷貝初始化將在如下情況下發生:

  • 用=定義變數
  • 將一個物件作為實參傳遞給一個非引用型別的形參
  • 從一個返回型別為非引用型別的函式返回一個物件
  • 用花括號列表初始化一個數組中的元素或一個聚合類中的成員

  如果使用的初始化值要求通過一個explicit的建構函式來進行型別轉換,那麼使用拷貝初始化還是直接初始化有比較大的區別:

vector<int> v1(10);    //正確:直接初始化
vector<int> v2 = 10;    //錯誤:接受大小引數的建構函式是explicit的
void f(vector<int>);    //f的引數進行拷貝初始化
f(10);                    //錯誤:不能用一個explicit的建構函式拷貝一個實參
f(vector<int>(10));        //正確:從int直接構造一個臨時vector

拷貝賦值運算子

    如果我們沒有為一個類定義拷貝賦值運算子,編譯器會為我們定義一個。對於某些類,合成拷貝拷貝賦值運算子用來禁止該型別物件的賦值。

  賦值運算子通常應該返回一個指向其左側運算物件的引用。

class Foo{
public:
    Foo& operator=(const Foo&);
    //……
};

解構函式

  解構函式釋放物件使用的物件,並銷燬物件的非static資料成員。沒有返回值,不接受引數。由於不接受引數,所以不能被過載。因此,對於一個給定類,只會有唯一一個解構函式。

  • 需要解構函式的類也需要拷貝和賦值操作
  • 需要拷貝操作的類也需要賦值操作,反之亦然

​​​​​​​使用=default

  當我們在類內使用=default修飾成員的宣告時,合成的海曙將隱式宣告為內聯的。如果不希望合成的成員是行內函數,應該只對創業的類外定義使用=default。只能對具有合成版本的成員函式使用=default(即,預設建構函式或拷貝控制成員)