2017-02-16 100 views
0

當引用刪除功能我有下面的類定義:使用的unique_ptr

class InterpolatedSpreadConnector 
{ 
public: 
    ~InterpolatedSpreadConnector() = default; 
    GPUImage* operator()() override; 

    GPUImage* AncestorReducedConnectivity = nullptr; 
    GPUImage* OffspringReducedConnectivity = nullptr; 
}; 

,其中,在auto connector = InterpolatedSpreadConnector();工作得很好聲明中使用時。但是,我想將這些原始指針更改爲unique_ptr

包括memory並且用定義中的std::unique_ptr<GPUImage>成員替換原始指針在InterpolatedSpreadConnector拷貝構造函數中給我一個attempting to reference deleted function錯誤。奇怪的是,如果我用shared_ptr代替unique_ptr,錯誤消失。

任何人都可以解釋爲什麼會發生這種情況?

+2

「唯一」表示不可複製或分配。但更好的發佈[mcve]。 – juanchopanza

+0

閱讀下面的內容:http://en.cppreference.com/w/cpp/language/copy_initialization – Nim

+0

我以爲有些東西就像複製elision(?),它會自動跳過複製構造並在這些情況下假定爲正常構造。 –

回答

4

對於此代碼的工作,在C++ 17之前,您需要爲您的類定義一個移動構造函數。這可能如此簡單:

InterpolatedSpreadConnector(InterpolatedSpreadConnector &&) = default; 

您的用戶定義的析構函數意味着隱式生成移動構造函數被抑制。

而且沒有移動構造函數,複製/移動操作會回退到複製構造函數,這會導致編譯錯誤,因爲隱式生成的複製構造函數被刪除,因爲unique_ptr具有刪除的複製構造函數。


在C++ 14和前面,auto x = X();概念意味着我們創建臨時X然後複製/移動-構建從臨時x並破壞臨時。編譯器允許臨時使用elide,但該過程的正確構造函數仍然存在。

但是在C++ 17中,auto x = X();將被定義爲與X x{};相同。

因此,您的代碼將在C++ 17中工作,不過無論如何定義移動構造函數是個好主意;或者最好刪除析構函數定義(請參閱Rule of zero)。

+0

我明白了。我認爲copy elision會自動跳過複製結構,並在這些情況下假設正常施工。 –

+1

@ KristianD'Amato它的確如此,但是如果複製elision沒有發生,將使用的構造函數必須存在並且可以訪問。其基本原理是,如果編譯器決定做或不做複製刪除,程序不應該突然無法編譯,這取決於選擇。 –