第十三章 拷貝控制

  1. 在定義任何 C++ 類時,拷貝控制操作都是必要部分。如果我們不顯示定義這些操作,編譯器也會爲我們定義,但編譯器定義的版本的行爲可能並非我們所想。
  2. 拷貝初始化不僅在我們用=定義變量時會發生,在下列情況下也會發生:
        ① 將一個對象作爲實參傳遞給一個非引用類型的形參;
        ② 從一個返回類型爲非引用類型的函數返回一個對象;
        ③ 用花括號列表初始化一個數組中的元素或一個聚合類中的成員。
  3. 重載運算符本質上是函數,其名字有 operator 關鍵字後接表示要定義的運算符的符號組成。因此,賦值運算符就是一個名爲 operator= 的函數。
  4. 某些運算符,包括賦值運算符,必須定義爲成員函數。如果一個運算符是一個成員函數,其左側運算對象就綁定到隱式的 this 參數。
  5. 在一個析構函數中,首先執行函數體,然後銷燬成員。成員按照初始化順序的逆序銷燬。
  6. 在一個析構函數中,不存在類似構造函數中初始化列表的東西來控制成員如何銷燬,析構部分是隱式的。銷燬類類型的成員需要執行成員自己的析構函數。內置類型沒有析構函數,因此銷燬內置類型成員什麼也不需要做。
  7. 隱式銷燬一個內置指針的成員不會 delete 它所指向的對象。而智能指針是類類型,所以具有析構函數。
  8. 如果一個類需要自定義析構函數,幾乎可以肯定它也需要自定義拷貝賦值運算符和拷貝構造函數。
  9. 對於析構函數已刪除的類型,不能定義該類型的變量或釋放指向該類型動態分配對象的指針。
  10. 如果一個類有數據成員不能默認構造、拷貝、複製或銷燬,則對應的成員函數被定義爲刪除的。
  11. 希望阻止拷貝的類應該使用 =delete 來定義它們自己的拷貝構造函數和拷貝賦值運算符,而不應該將它們聲明爲 private 。
  12. 當你編寫賦值運算符時,有兩點需要記住:
        ① 如果將一個對象賦予它自身,賦值運算符必須能正確工作;
        ② 大多數賦值運算符組合了析構函數和拷貝構造函數的工作。
        (當你編寫一個賦值運算符時,一個好的模式是先將右側運算對象拷貝到一個局部臨時對象中。)
  13. 與拷貝控制成員不同, swap 並不是必要的。但是,對於分配了資源的類,定義 swap 可能是一種很重要的優化手段。
  14. 使用拷貝和交換的賦值運算符自動就是異常安全的,且能正確處理自賦值。
  15. 返回左值引用的函數,連同賦值、下標、解引用和前置遞增/遞減運算符,都是左值的表達式的例子。返回非引用類型的函數,連同算數、關係、位及後置遞增/遞減運算符,都生成右值。
  16. 左值有持久的狀態,而右值要麼是字面常量,要麼是在表達式求值過程中創建的臨時對象。(右值引用所引用的對象將要被銷燬,或者該對象沒有其他用戶)
  17. 變量是左值,因此我們不能將一個右值引用直接綁定到一個變量上,即使這個變量時右值引用類型也不行。
  18. 除非標準庫知道我們的移動構造函數不會拋出異常,否則它會認爲移動我們的類對象時可能會拋出異常,並且爲了處理這種可能性而做一些額外的工作。
  19. 不拋出異常的移動構造函數和移動賦值運算符必須標記爲 noexcept 。
  20. 除非 vector 知道元素類型的移動構造函數不會拋出異常,否則在重新分配內存的過程中,它就必須使用拷貝構造函數而不是移動構造函數。
  21. 在移動操作之後,移後源對象必須保持有效的、可析構狀態,但是用戶不能對其值進行任何假設。
  22. 如果一個類定義了自己的拷貝構造函數、拷貝賦值運算符或析構函數,編譯器就不會爲它合成移動構造函數和移動賦值運算符了。
  23. 只有當一個類沒有定義任何自己版本的拷貝控制成員,且它的所有數據成員都能移動構造或移動賦值時,編譯器纔會爲它合成移動構造函數或移動賦值運算符。
  24. 如果移動操作可能被定義爲刪除的函數,編譯器就不會合成它們。
  25. 定義了一個移動構造函數或移動賦值運算符的類必須也定義自己的拷貝操作,否則,這麼成員默認地被定義爲刪除的。
  26. 移動右值,拷貝左值,但如果沒有移動構造函數,右值也被拷貝。(可以將 && 轉換爲 const &)
  27. 所有五個拷貝控制成員應該看做一個整體:一般來說,如果一個類定義了任何一個拷貝控制操作,它就應該定義所有五個操作。
  28. 除了構造函數和賦值運算符外,如果一個成員函數同事提供拷貝和移動版本,它也能從中受益。
  29. 對於 & 限定的函數,我們只能將它用於左值;對於 && 限定的函數,只能用於右值。
  30. 如果一個成員函數有引用限定符,則具有相同參數列表的所有版本都必須有引用限定符。
  31. 調用 move 隱含地承諾我們將不會再使用移後源對象,除了銷燬它或賦予它一個新值之外。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章