delete又未完全delete

反直覺C++??, ??歡迎github star

delete又未完全delete

假設(shè)我們要定義一個(gè)這樣的類:只支持拷貝操作不支持移動(dòng)操作。

#include <iostream>

class Test {
public:
    Test() {
        std::cout << "constructor\n";
    }

    Test(const Test& test) {
        std::cout << "copy constructor\n";
    }
    Test& operator=(const Test& test) {
        std::cout << "copy assignment operator\n";
        
        return *this;
    };

    Test(Test&& test) = delete;
    Test& operator=(Test&& test) = delete;
};

Test getTest() {
    Test test;
    return test;
}

int main() {
    Test test{ getTest() };

    return 0;
}

輸出

main.cpp: In function 'Test getTest()':
main.cpp:16:12: error: use of deleted function 'Test::Test(Test&&)'
   16 |     return test;
      |            ^~~~
main.cpp:10:5: note: declared here
   10 |     Test(Test&& test) = delete;
      |     ^~~~
main.cpp:16:12: note: use '-fdiagnostics-all-candidates' to display considered candidates
   16 |     return test;
      |            ^~~~

從編譯錯(cuò)誤信息可以看出,被顯式deleteTest(Test&& test)參與到了重載決議,且被認(rèn)為比拷貝構(gòu)造版本更好,但移動(dòng)構(gòu)造版本被指定了刪除不能被使用,所以編譯器報(bào)錯(cuò)。
指定了刪除,卻未完全刪除,參與到了重載決議,有點(diǎn)反直覺。

奇怪的知識(shí)增加了

刪除的移動(dòng)構(gòu)造函數(shù)仍然是一個(gè)已聲明的函數(shù),有資格進(jìn)行重載解析。getTest函數(shù)按值返回將優(yōu)先選擇刪除的移動(dòng)構(gòu)造函數(shù)而非未刪除的復(fù)制構(gòu)造函數(shù)。

#include <iostream>

class Test {
public:
    Test() {
        std::cout << "constructor\n";
    }

    Test(const Test& test) {
        std::cout << "copy constructor\n";
    }
    Test& operator=(const Test& test) {
        std::cout << "copy assignment operator\n";
        
        return *this;
    };

    Test(Test&& test) = default;
    Test& operator=(Test&& test) = delete;
};

Test getTest() {
    Test test;
    return test;
}

int main() {
    Test test{ getTest() };

    return 0;
}

輸出

constructor
#include <iostream>

class Test {
public:
    Test() {
        std::cout << "constructor\n";
    }

    Test(const Test& test) {
        std::cout << "copy constructor\n";
    }
    Test& operator=(const Test& test) {
        std::cout << "copy assignment operator\n";
        
        return *this;
    };

    Test(Test&& test) {
        std::cout << "move constructor\n";
    }
    Test& operator=(Test&& test) = delete;
};

Test getTest() {
    Test test;
    return test;
}

int main() {
    Test test{ getTest() };

    return 0;
}

輸出

constructor

Test(Test&& test) = delete修改為Test(Test&& test) = default或者顯式定義雖可以修復(fù)此問(wèn)題,然而,之前的本意就是將移動(dòng)構(gòu)造刪除,讓其使用拷貝構(gòu)造啊,如此修改違背了本意。
更進(jìn)一步的觀察,竟然未輸出move constructor!重載決議選擇了移動(dòng)構(gòu)造,但未執(zhí)行移動(dòng)構(gòu)造,有點(diǎn)反直覺,此問(wèn)題請(qǐng)參考尾返回值優(yōu)化。

C++11之前可以通過(guò)“只聲明不實(shí)現(xiàn)”的方式要?jiǎng)h除函數(shù),既然尾返回值優(yōu)化可以優(yōu)化掉拷貝構(gòu)造的調(diào)用,那我們可以保證編譯通過(guò)即可。

#include <iostream>

class Test {
public:
    Test() {
        std::cout << "constructor\n";
    }

    Test(const Test& test) {
        std::cout << "copy constructor\n";
    }
    Test& operator=(const Test& test) {
        std::cout << "copy assignment operator\n";
        
        return *this;
    };

    Test(Test&& test);
    Test& operator=(Test&& test) = delete;
};

Test getTest() {
    Test test;
    return test;
}

int main() {
    Test test{ getTest() };

    return 0;
}

輸出

constructor

從上述代碼表現(xiàn)來(lái)看,移動(dòng)構(gòu)造只參與了重載決議,未參與鏈接和運(yùn)行期運(yùn)行!

最后我們?cè)賴L試一個(gè)移動(dòng)構(gòu)造參與鏈接器鏈接的版本:

#include <iostream>

class Test {
public:
    Test() {
        std::cout << "constructor\n";
    }

    Test(const Test& test) {
        std::cout << "copy constructor\n";
    }
    Test& operator=(const Test& test) {
        std::cout << "copy assignment operator\n";
        
        return *this;
    };

    Test(Test&& test);
    Test& operator=(Test&& test) = delete;
};

Test getTest() {
    Test test;
    return std::move(test);
}

int main() {
    Test test{ getTest() };

    return 0;
}

輸出

/tmp/cc3TH4WE.o: In function `getTest()':
main.cpp:(.text+0x32): undefined reference to `Test::Test(Test&&)'
collect2: error: ld returned 1 exit status

重載決議選擇了移動(dòng)構(gòu)造,但是鏈接時(shí)未找到移動(dòng)構(gòu)造的實(shí)現(xiàn)!

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • Java 常見英語(yǔ)單詞 (1.0 版本) 1. Java 基礎(chǔ)常見英語(yǔ)詞匯(70 個(gè)) OO: object-or...
    Nemo359閱讀 2,637評(píng)論 0 0
  • Java基礎(chǔ)常見英語(yǔ)詞匯(共70個(gè))['?bd?ekt] ['?:rientid]導(dǎo)向的 ...
    今夜子辰閱讀 3,487評(píng)論 1 34
  • 教程鏈接:C語(yǔ)言中文網(wǎng) C++教程[http://c.biancheng.net/view/2189.html] ...
    縱橫Top閱讀 358評(píng)論 0 0
  • 1. Java基礎(chǔ)部分 基礎(chǔ)部分的順序:基本語(yǔ)法,類相關(guān)的語(yǔ)法,內(nèi)部類的語(yǔ)法,繼承相關(guān)的語(yǔ)法,異常的語(yǔ)法,線程的語(yǔ)...
    子非魚_t_閱讀 34,740評(píng)論 18 399
  • 1.C和C++的區(qū)別?C++的特性?面向?qū)ο缶幊痰暮锰帲?答:c++在c的基礎(chǔ)上增添類,C是一個(gè)結(jié)構(gòu)化語(yǔ)言,它的重...
    杰倫哎呦哎呦閱讀 10,007評(píng)論 0 45

友情鏈接更多精彩內(nèi)容