2015-01-07 81 views
7

我的問題涉及如何返回沒有拷貝構造函數的對象。舉個例子,我們假設我有一些bigResource位於堆中,我們假設我使用unique_ptr來跟蹤它。現在假設我將這種資源的所有權交給毛蟲。然後我有一個CaterpillarWithBigResource。現在在某個時候,這個CaterpillarWithBigResource將變爲ButterflyWithBigResource,因此Caterpillar對象將不得不將所有權轉移給Butterfly對象。如何返回沒有拷貝構造函數的對象

我寫了下面的代碼的情況型號:

#include <cstdlib> 
#include <iostream> 
#include <memory> 

class ButterflyWithBigResource { 
public: 

    // If I uncomment just this line, I get an error 
    // ButterflyWithBigResource(const ButterflyWithBigResource& other) = default; 

    // If I uncomment just this line, I get an error 
    // ButterflyWithBigResource(const ButterflyWithBigResource& other) = delete; 

    // With both above lines commented out, I get no errors, and the program runs fine. 

    ButterflyWithBigResource(std::unique_ptr<int>&& bigResource) : 
    bigResource(std::move(bigResource)) { 

    } 

    const int& getResource() { 
     return *bigResource; 
    } 

private: 
    std::unique_ptr<int> bigResource; 
}; 

class CaterpillarWithBigResource { 
public: 

    CaterpillarWithBigResource(int bigResource) : 
    bigResource(new int(bigResource)) { 

    } 

    ButterflyWithBigResource toButterfly() && { 
     return ButterflyWithBigResource(std::move(bigResource)); 
    } 
private: 
    std::unique_ptr<int> bigResource; 
}; 

/* 
* 
*/ 
int main(int argc, char** argv) { 
    CaterpillarWithBigResource caterpillarWithBigResource(5); 
    ButterflyWithBigResource butterflyWithBigResource(std::move(caterpillarWithBigResource).toButterfly()); 
    std::cout << butterflyWithBigResource.getResource() << std::endl; 
    return 0; 
} 

注意,無論是Caterpillar還是Butterfly有默認的拷貝構造函數,因爲他們每個人都有一個unique_ptr。然而,我不希望這是問題,所以只有移動構造函數纔是必要的。畢竟,我只是將所有權從Caterpillar轉移到Butterfly

事實上,當我使用g++版本4.8.2編譯程序g++ -c -g -std=c++11 -MMD -MP -MF它工作得很好。

但現在奇怪的是,如果我要提醒的是,Butterfly的拷貝構造函數被刪除編譯器通過將線ButterflyWithBigResource(const ButterflyWithBigResource& other) = delete;,程序不再編譯,編譯器抱怨的拷貝構造函數被刪除,這樣我可以在toButterfly方法中不返回Butterfly

如果我然後試着告訴它,一切正常,而不是行ButterflyWithBigResource(const ButterflyWithBigResource& other) = default;,我再次得到相同的錯誤。

我希望發生的是在toButterfly方法構建的Butterfly被轉移到toButterfly的返回地址,再後來用作Butterfly的說法「在main()構建butterflyWithBigResource時的舉動的構造。有沒有辦法做到這一點?

+0

BTW,返回,沒有拷貝構造一個對象,你會使用複印通list-initialization:'return {std :: move(bigRes我們)}' – 0x499602D2

回答

7

當您註釋掉明確defaultdelete拷貝構造函數的行時,編譯器可以自由爲您隱式生成移動構造函數(並移動賦值運算符)。

通過明確default ing或delete複製構造函數,可以禁止隱式生成移動構造函數。

從N3337,§12.8/ 9[class.copy]

如果一個類X的定義不明確宣佈此舉的構造函數,一個將被隱式聲明爲默認,如果和只有當
- X沒有一個用戶聲明的拷貝構造函數,
- ...

不再生成移動構造函數時,必須複製toButterfly()的返回值,但無論您是否默認或刪除了複製構造函數,都會失敗。

如果您使用default複製構造函數,編譯器由於存在unique_ptr數據成員(不可複製)而無法生成默認的複製構造函數實現。

當您複製構造函數,如果它通過重載決議被選中,這是一個錯誤。


你不應該直接刪除,因爲拷貝構造函數,如上所述,該unique_ptr數據成員的存在暗示其刪除,但如果你想這樣做,那麼你還需要明確默認情況下,移動構造函數(和移動賦值運算符太,如果你想移動分配工作)

ButterflyWithBigResource(ButterflyWithBigResource&&) = default; 
ButterflyWithBigResource& operator=(ButterflyWithBigResource&&) = default; 

Live demo

+0

哦,那很簡單。 –

+0

修復了它。在我的真實代碼中,我有'virtual〜C()= default;'。 –

+1

@NowIGetToLearnWhatAHeadIs * - 'X'沒有用戶聲明的析構函數*是上面列表中的第四個項目符號:) – Praetorian