1. 程式人生 > >C++ primer 13.1:拷貝、賦值和析構

C++ primer 13.1:拷貝、賦值和析構

拷貝構造函數 阻止 需要 函數 static let default 個數 調用

1.拷貝構造函數 基本形式:Name(const Name&) 對於類類型成員,會調用拷貝構造函數拷貝,對於內置類型成員就直接拷貝。對於數組,合成的拷貝構造函數會逐個拷貝都另一個數組中(內置類型)。 拷貝構造函數發生的時候:
  • 發生在用 = 定義變量時
  • 將一個對象作為實參傳遞給一個非引用類型的形參
  • 從一個返回類型為非飲用類型的函數返回一個對象
  • 用花括號列表初始化一個數組中的元素或一個聚合類中的成員
註意:拷貝構造函數第一個參數必須是自身的引用,因為拷貝構造函數是用來初始化非引用類類型參數,如果參數不是自身的引用,那麽不會調用成功,會無限循環。為了調用拷貝構造函數會拷貝實參,這樣又會調用拷貝構造函數。
2.拷貝賦值運算符(出現在賦值時) 基本形式:Name& operator = (const Name&) 通常來說應該返回指向指向左側運算對象的引用。會將右側非static對象賦值給左側成員。合成的拷貝賦值運算符會逐個賦值數組元素(內置類型)。
3.析構函數 釋放對象使用的資源,並銷毀對象的非static數據成員。 析構函數發生的時候:
  • 變量在離開其作用域時被銷毀
  • 當一個對象被銷毀時,其成員被銷毀
  • 容器被銷毀時,其元素被銷毀(包括數組)
  • 動態分配的對象,當對指向它的指針應用delete運算符時被銷毀
  • 臨時對象,當創建它的完整表達式結束時被銷毀(作用域)
註意:析構函數自身並不銷毀成員,成員是在析構函數體之後隱含析構階段中被銷毀的。在整個對象銷毀過程中,析構函數體是作為成員銷毀步驟之外的另一部分而進行的。
4.三五法則 1.需要析構函數的類需要拷貝和賦值操作 2.需要拷貝操作的類也需要賦值操作
5.使用 = default 可以在拷貝控制成員定義為如下: Name() = default; //默認構造函數 Name(const Name&) = default; Name& operator = (const Name&) = default; ~Name() = default; 來顯示說明使用編譯器合成版本。
6.使用 = delete 也可以如下定義: Name() = delete; //默認構造函數 Name(const Name&) = delete; Name& operator = (const Name&) = delete; 析構函數不能聲明為被刪除 來說明阻止的拷貝賦值操作(老標準可以把這些放進private阻止拷貝)。對於某些類來說,拷貝賦值操作沒有意義。 註意:= delete必須出現在函數第一次聲明的時候,而 = default直到編譯器生成代碼時才需要。同時也可以對其他任何函數使用= delete。
7.合成的拷貝控制成員可能是刪除的 出現以下情況,合成的拷貝控制成員會被定義為刪除:
  • 如果類的某個成員的析構函數是刪除的或不可訪問,則析構函數被定義為刪除
  • 如果類的某個成員的拷貝構造函數是刪除的或不可訪問的,則類的合成拷貝構造函數被定義為刪除的。
  • 如果類的某個成員的析構函數是刪除的或不能不可訪問的,則類的合成拷貝構造函數也定義為刪除的。
  • 如果類的某個成員的拷貝賦值運算符是刪除的或不可訪問的,或是類有一個const或引用成員,則類的合成拷貝賦值運算符被定義為刪除的。
  • 如果類的某個成員的析構函數是刪除的或不可訪問的,或是類有一個引用成員,它沒有類內初始化器,或是類有一個const成員,它沒有類內初始化器且其類型未顯示定義默認構造函數,則該類的默認構造函數被定義為刪除的。

C++ primer 13.1:拷貝、賦值和析構