天天看點

C++11新特性:default函數、delete函數

1、預設函數:

C++ 的類有四類特殊成員函數,它們分别是:預設構造函數、析構函數、拷貝構造函數以及拷貝指派運算符。這些類的特殊成員函數負責建立、初始化、銷毀,或者拷貝類的對象。

如果程式員沒有顯式地為一個類定義某個特殊成員函數,而又需要用到該特殊成員函數時,則編譯器會隐式的為這個類生成一個預設的特殊成員函數。

2、=default:

C++11 标準引入了一個新特性:"=default"函數。程式員隻需在函數聲明後加上“=default;”,就可将該函數聲明為 "=default"函數,編譯器将為顯式聲明的 "=default"函數自動生成函數體。

  • "=default"函數特性僅适用于類的特殊成員函數,且該特殊成員函數沒有預設參數;
  • "=default"函數既可以在類體裡(inline)定義,也可以在類體外(out-of-line)定義。

我們看一些示例:

class X { 
public: 
    X() = default; //該函數比使用者自己定義的預設構造函數獲得更高的代碼效率
    X(int i) { 
        a = i; 
    }
private: 
    int a; 
}; 

X obj;

// "=default"函數特性僅适用于類的特殊成員函數,且該特殊成員函數沒有預設參數。
class X1{
public:
    int f() = default;      // err , 函數 f() 非類 X 的特殊成員函數
    X1(int, int) = default;  // err , 構造函數 X1(int, int) 非 X 的特殊成員函數
    X1(int = 1) = default;   // err , 預設構造函數 X1(int=1) 含有預設參數
};

// "=default"函數既可以在類體裡(inline)定義,也可以在類體外(out-of-line)定義。
class X2{
public:
    X2() = default; //Inline defaulted 預設構造函數
    X2(const X&);
    X2& operator = (const X&);
    ~X2() = default;  //Inline defaulted 析構函數
};

X2::X2(const X&) = default;  //Out-of-line defaulted 拷貝構造函數
X2& X2::operator= (const X2&) = default;   //Out-of-line defaulted  拷貝指派操作符      

3、=delete:

為了能夠讓程式員顯式的禁用某個函數,C++11 标準引入了一個新特性:"=delete"函數。程式員隻需在函數聲明後上“=delete;”,就可将該函數禁用。

  • "=delete"函數特性可用于禁用類的某些轉換構造函數,進而避免不期望的類型轉換;
  • "=delete"函數特性還可以用來禁用某些使用者自定義的類的 new 操作符,進而避免在自由存儲區建立類的對象;
  • "=delete"函數特性還可以用來禁用拷貝構造函數、拷貝指派函數;
class X3 {
public:
    X3();
    X3(const X3&) = delete;  // 聲明拷貝構造函數為 deleted 函數
    X3& operator = (const X3 &) = delete; // 聲明拷貝指派操作符為 deleted 函數
};
class X4 {
public:
    X4(double){}
    X4(int) = delete;// "=delete"函數特性還可用于禁用類的某些轉換構造函數,進而避免不期望的類型轉換
};
// "=delete"函數特性還可以用來禁用某些使用者自定義的類的 new 操作符,進而避免在自由存儲區建立類的對象
class X5{
public:
    void *operator new(size_t) = delete;
    void *operator new[](size_t) = delete;
};

void mytest(){
    X4 obj1;
    X4 obj2=obj1;   // 錯誤,拷貝構造函數被禁用

    X4 obj3;
    obj3=obj1;     // 錯誤,拷貝指派操作符被禁用

    X5 *pa = new X5;      // 錯誤,new 操作符被禁用
    X5 *pb = new X5[10];  // 錯誤,new[] 操作符被禁用
    return;
}