簡體   English   中英

為什么刪除move構造函數會導致編譯錯誤?

[英]Why does deleting the move constructor cause a compile error?

以下代碼可以正常工作:

#include <iostream>
using namespace std;
struct oops
{
        ~oops()
        {
                cout << " oops! " << endl;
        }
};

struct sample
{
        oops* x = nullptr;
        sample(oops* p) : x(p)
        {
                cout << "sample: " << p << endl;
        }
        ~sample()
        {
                delete x;
                cout << "destroy sample " << endl;
        }
        sample(const sample&)
        {
                cout << "copy sample " << endl;
        }
        sample(sample&&)
        {
                cout << "move sample " << endl;
        }
};

int main()
{
        sample s = new oops;
        return 0;
}

結果:

sample: 0x1470c20
 oops!
destroy sample

它清楚地表明,移動和復制構造函數都沒有被調用。 刪除這些構造函數時

sample(const sample&) = delete;
sample(sample&&) = delete;

gcc給出了編譯錯誤:

bpp.cpp: In function ‘int main()’:
bpp.cpp:29:17: error: use of deleted function ‘sample::sample(sample&&)’
  sample s = new oops;
                 ^
bpp.cpp:24:2: note: declared here
  sample(sample&&) = delete;
  ^
bpp.cpp:14:2: note:   after user-defined conversion: sample::sample(oops*)
  sample(oops* p) : x(p)
  ^

這與-fno-elide-constructors有什么關系嗎? 如何在不定義這些構造函數或使用顯式構造函數的情況下編譯它?

編輯:我的GCC版權是5.4.0。 命令是:

g++ bpp.cpp -std=c++17
sample s = new oops;

這是一種復制初始化的形式。 對於編譯器來解決它直到C ++ 17,必須存在復制或移動構造函數。 但是,由於優化(使用GCC和-fno-elide-constructors ,調用移動構造函數),編譯器可以自由地調用它的調用。

從C ++ 17開始,這些構造函數都不是必需的: https//wandbox.org/permlink/3V8glnpqF5QxljJl


如何在不定義這些構造函數或使用顯式構造函數的情況下編譯它?

非常簡單,避免復制初始化並使用直接初始化

sample s { new oops };

或者,使用C ++ 17。

為什么這不能編譯?

這行代碼:

sample s = new oops;

相當於寫作:

sample s = sample(new oops);

在C ++ 11和C ++ 14中,這隱式調用移動構造函數(或復制構造函數,如果沒有移動構造函數可用)。 因為允許編譯器省略副本和移動,所以實際移動被省略,並且在調用移動構造函數時它不會顯示任何內容。 即使實際移動被省略,也不允許程序隱含地引用已刪除的函數,因此存在編譯器錯誤。

您可以通過將初始化更改為任一來解決此問題

sample s { new oops };

要么

sample s ( new oops );

或者,如果你真的想使用= ,你可以利用臨時的生命周期擴展來寫

// s won't get destroyed until the end of the scope
// it's safe to use s after this statement
sample&& s = new oops;

C ++ 17有什么變化?

C ++ 17對對象所屬的值類別集進行了一些更改。在C ++ 17中, sample(new oops)成為prvalue,而c ++ 17標准要求編譯器必須將prvalues放入到位復制或移動它們。 這是通過黑暗魔法和巫術的結合來完成的。

這意味着sample s = new oops; 在c ++ 17中是合法的

為什么在添加-std=c++17時仍然無法編譯?

這段代碼應該在C ++ 17下編譯 ,並且你得到的錯誤是因為gcc 6.3和更早版本沒有實現c ++ 17標准的那部分。 此問題已在gcc 7.1中修復,代碼將按預期編譯。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM