C++:= delete

= delete

delete的由來

如以前提到的,在沒有聲明默認特殊成員函數的時候,編譯器會自動幫咱們補充,但有時候咱們並不但願存在這些函數,好比:咱們不但願某個類經過拷貝的方式實例化一個新的對象。就算咱們不定義拷貝構造函數和重載拷貝賦值運算符,編譯器也會爲咱們自動完成。c++

#include <bits/stdc++.h>
using namespace std;

class LiF {
public:
    LiF() = default;
    LiF(int _lif) {
        lif = _lif;
    }
    void print(){cout << lif << endl;}
    ~LiF() = default;
private:
    int lif;
};

int main() {
    LiF* lif1 = new LiF{2};
    LiF lif2 = *lif1; // 咱們不但願這個類能夠拷貝構造
    lif2.print();
    delete lif1;
    lif1 = nullptr;
    return 0;
}

寫出如上代碼以後,編譯能夠經過,但違反了咱們的初衷。函數

再看下面這個場景:spa

double add(double x, double y) {
    return x + y;
}

int main() {
    int a, b;
    add(a, b);
    return 0;
}

這裏咱們聲明瞭double類型的add函數,編譯能夠經過。假設此時咱們不但願其餘類型能經過隱式轉換調用這個函數,那這裏就須要禁用掉會發生轉換的版本。code

由此C++11引入了delete關鍵字,用於顯式禁用某些函數。對象

delete示例

default不一樣的是,delete沒有限制函數必須是類的特殊成員函數。作用域

#include <bits/stdc++.h>
using namespace std;

class LiF {
public:
    LiF() = default;
    LiF(int _lif) {
        lif = _lif;
    }
    LiF(const LiF& l) = delete; // 顯式禁用拷貝構造函數
    LiF& operator= (const LiF& l) = delete; // 顯式禁用拷貝賦值運算符

    void print(){cout << lif << endl;}

    ~LiF() = default;
private:
    int lif;
};

int main() {
    LiF* lif1 = new LiF{2};
    LiF lif2 = *lif1; // 這裏將引起報錯,由於拷貝賦值運算符已被顯式禁用
    lif2.print();
    delete lif1;
    lif1 = nullptr;
    return 0;
}
double add(double x, double y) {
    return x + y;
}
int add(int, int) = delete; // 顯式禁用add函數的int版本

int main() {
    int a, b;
    add(a, b); // 這裏將引起報錯,由於對應的函數已被顯式禁用
    return 0;
}

這裏有一點須要注意的是,delete關鍵字僅僅禁用了函數的調用,但在編譯過程當中,名字查找和重載解析時,該函數名還是一個有效的標識符。編譯器

分析第二個例子:咱們聲明並定義了double類型的add函數,聲明並顯式禁用了add函數的int重載。在編譯到add(a, b)時,編譯器進行名字查找,找到全局做用域的add函數定義,並經過精確匹配最終定位到int add(int, int)這個重載上,隨後編譯器發現這是一個deleted(已被禁用)函數,引起報錯。it

相關文章
相關標籤/搜索