C++:= delete聲明


= delete

delete的由來

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

#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;
}

寫出如上代碼之后,編譯可以通過,但違反了我們的初衷。

再看下面這個場景:

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

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

這里我們聲明了double類型的add函數,編譯可以通過。假設此時我們不希望其他類型能通過隱式轉換調用這個函數,那這里就需要禁用掉會發生轉換的版本。

由此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(已被禁用)函數,引發報錯。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM