1.為什么要阻止類對象的拷貝?
1)有些類,不需要拷貝和賦值運算符,如:IO類,以避免多個拷貝對象寫入或讀取相同的IO緩沖
2.如何阻止?
1)不定義拷貝構造函數和拷貝賦值運算符時,好心的編譯器也會及時地學習雷鋒好榜樣幫你合成定義,即傳說中的合成拷貝構造、合成拷貝賦值,所以這樣阻止不了
2)c++11允許使用“=delete”將拷貝構造函數和拷貝賦值運算符定義為刪除的函數,在函數參數列表后加上“=delete”即表明這個函數是刪除的函數
3)刪除的函數是一種這樣的函數:我們雖然聲明了它,但是不能使用它
4)"=delete"的主要用途是阻止類的拷貝賦值,但也可以指定給非拷貝控制成員
3.=delete和=default的區別
1)"=delete"必須出現在函數第一次聲明的時候;而"=default"沒有這個要求
2)語法上允許對任何函數都可以指定"=delete",不局限於類的成員函數,但一般情況下對析構函數不指定;而語法上只能對默認構造函數和五個拷貝控制成員使用"=default"
4.合成版本的拷貝成員函數可能被編譯器定義為delete
1)某個數據成員的拷貝構造函數是刪除的或不可訪問的(private),則這個類的合成拷貝構造函數會被編譯器定義為delete
2)某個數據成員的拷貝賦值運算符是刪除的或不可訪問的(private),或者類有一個const成員,或者類有一個引用成員,則這個類的合成拷拷貝賦值運算符會被編譯器定義為delete
3)特殊情況:定義了一個移動構造函數或移動賦值運算符的必須也定義自己的拷貝成員函數,否則,它們被編譯器合成的版本將為delete
4)規則總結:如果類的某個數據成員不能拷貝、賦值,則對應的合成版本的成員函數將被編譯器定義為delete。
5.合成版本的構造/析構函數可能被編譯器定義為delete
1)某個數據成員的析構函數是刪除的或不可訪問的(private),則這個類的合成析構函數會被編譯器定義為delete
2)某個數據成員的析構函數是刪除的或不可訪問的(private),或者類有一個const成員卻沒有類內初始值,或者類有一個引用成員卻沒有類內初始值,則這個類的合成構造函數會被編譯器定義為delete
6.合成版本的移動成員函數可能被編譯器定義為delete
1)如果顯式地用=default要求編譯器生成合成移動操作,且編譯器不能移動所有非static成員,則合成移動操作會被編譯器定義為delete.
7.c++11以前detele的替代品
1)在c++11之前,類可以通過將其拷貝構造函數和拷貝賦值運算符聲明為private來阻止拷貝,用戶不能使用它們來拷貝對象,試圖拷貝對象的代碼在編譯階段將被標記為錯誤
1 class A{ 2 private: 3 A(const A&); 4 A& operator=(const A&); 5 //其他成員省略 6 };