1. 程式人生 > >C++11新特性——default函式和deleted函式

C++11新特性——default函式和deleted函式

轉自http://blog.jobbole.com/103669/

default函式

  • default函式作用於類的特殊成員函式,為其自動生成預設的函式定義體,提高程式碼的執行效率。

  • 類的特殊成員函式:

    • 預設建構函式
    • 解構函式
    • 複製建構函式
    • 拷貝賦值運算子
    • 取址運算子
    • const取址運算子
  • 前四個特殊函式負責例項化物件、銷燬物件以及複製物件。如果類中沒有定義建構函式,則會生成一個預設建構函式。

#include<iostream>

using namespace std
; class A { public: int get() { return a; } private: int a; }; int main(int argc, char* argv[]) { A A1; //可以例項化物件,類有預設建構函式 cout << A1.get() << endl; getchar(); return 0; }
  • 但當類中含有建構函式時,類不會為其生成預設建構函式:
#include<iostream>

using namespace std;

class A {
public
: A(int a) { this->a = a; } int get() { return a; } private: int a; }; int main(int argc, char* argv[]) { //A A1; //錯誤:類A不存在預設建構函式 A A2(10); //正確:呼叫帶參的建構函式 cout << A2.get() << endl; //10 getchar(); return 0; }
  • 倘若我們想使用預設建構函式,則必須顯式地定義:
class A {
public:
    A(){}    //顯式地定義
    A(int a) {
        this->a = a;
    }
    int get() {
        return a;
    }
private:
    int a;
};
  • 顯式地定義預設建構函式存在問題:手動編寫的特殊成員函式的程式碼執行效率比編譯器自動生成的特殊函式低!

  • 此時default函式就正式登場了。C++11標準引入了一個新特性:default函式。程式設計師只需在類的特殊成員函式聲明後加上“=default;”,就可將該函式宣告為 defaulted 函式,編譯器將為顯式宣告的 defaulted 函式自動生成函式體。

class A {
public:
    A() = default;   //自動生成函式體
    A(int a) {
        this->a = a;
    }
    int get() {
        return a;
    }
private:
    int a;
};
  • 注意:

    • default函式僅適用於類的特殊成員函式,且該特殊成員函式沒有預設引數
    • default函式既可以在類內宣告類外定義,也可以在類內直接定義
class A {
public:
    A() = default;   //自動生成函式體,類內定義
    //A(double d) = default;  //錯誤:型別對於預設建構函式無效
    A(int a) {
        this->a = a;
    }
    A(const A& it);
    //int get() = default;  //錯誤:=default只能出現在預設建構函式、解構函式、複製建構函式、賦值運算子中
private:
    int a;
};

A::A(const A& it) = default;  //類內宣告,類外定義

deleted函式

  • 編譯器會對指定的函式禁用,從而避免了某些非法的函式呼叫或者型別轉換,從而提高了程式碼的安全性。

  • 對於 C++ 的類,如果程式設計師沒有為其定義特殊成員函式,那麼在需要用到某個特殊成員函式的時候,編譯器會隱式的自動生成一個預設的特殊成員函式,上面我們提到預設建構函式,還有複製建構函式,拷貝賦值操作符。(當初始化物件時呼叫的是複製建構函式,已經初始化過的物件呼叫的是賦值運算子)

#include<iostream>

using namespace std;

class A {
public:
    A() = default;   //自動生成函式體,類內定義
    A(int a) {
        this->a = a;
    }
private:
    int a;
};

int main(int argc, char* argv[]) {
    A A1(10);
    A A2 = A1;  //正確,呼叫編譯器隱式生成的預設複製建構函式
    A A3(20);
    A2 = A3;    //正確,呼叫編譯器隱式生成的賦值運算子
    getchar();
    return 0;
}
  • 編譯器能隱式地生成複製建構函式和賦值運算子當然有其優點:為程式設計師省掉了一些程式碼量,但在某些情況下,我們不允許發生類物件之間的複製和賦值,可是又無法阻止編譯器隱式自動生成預設的拷貝建構函式以及拷貝賦值操作符,那這就成為一個問題了。

  • deleted函式正式登場了。C++11 標準引入了一個新特性:deleted 函式。程式設計師只需在函式聲明後加上“=delete;”,就可將該函式禁用。

#include<iostream>

using namespace std;

class A {
public:
    A() = default;   //自動生成函式體,類內定義
    A(int a) {
        this->a = a;
    }
    A(const A& it) = delete;
    A& operator=(const A& it) = delete;
private:
    int a;
};

int main(int argc, char* argv[]) {
    A A1(10);
    //A A2 = A1;  //錯誤:複製建構函式是已刪除的函式
    A A3(20);
    //A2 = A3;    //錯誤:賦值運算子函式是已刪除的函式
    getchar();
    return 0;
}
  • 注意

    • 必須在函式第一次宣告的時候將其宣告為 deleted 函式,否則編譯器會報錯
    • deleted 函式特性可以作用於類的特殊成員函式、類的非特殊成員函式、普通函式。
#include<iostream>

using namespace std;

class A {
public:
    A() = default;   //自動生成函式體,類內定義
    A(int a) {
        this->a = a;
    }
    A(const A& it);
    A& operator=(const A& it) = delete;  //正確:“=delete”出現在函式的第一個宣告中
    int get() = delete;   //正確:“=delete”特性可以作用於類的非特殊成員函式
private:
    int a;
};
//A::A(const A& it) = delete;  //錯誤:“=delete”只能出現在函式的第一個宣告中

int fun1() = delete;  //正確:“=delete”特性可以作用於普通函式

int main(int argc, char* argv[]) {
    A A1(10);
    //A A2 = A1;  //錯誤:複製建構函式是已刪除的函式
    A A3(20);
    //A2 = A3;    //錯誤:賦值運算子函式是已刪除的函式
    //A3.get();   //錯誤:get()函式是已刪除的函式
    getchar();
    return 0;
}