2015-01-07 24 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++ -c -g -std=c++11 -MMD -MP -MFg++ संस्करण 4.8.2 का उपयोग कर प्रोग्राम संकलित करता हूं तो यह ठीक काम करता है।

लेकिन अब अजीब बात यह है कि अगर मैं लाइन ButterflyWithBigResource(const ButterflyWithBigResource& other) = delete; जोड़कर संकलक कि Butterfly की कॉपी निर्माता हटा दी जाती है याद दिलाना, कार्यक्रम अब संकलित, और संकलक शिकायत है कि प्रति निर्माता हटा दी जाती है, ताकि मैं toButterfly विधि में Butterfly वापस न करें।

मैं तो है कि सब कुछ के बजाय लाइन ButterflyWithBigResource(const ButterflyWithBigResource& other) = default; होने से ठीक है यह बताने के लिए कोशिश करते हैं, तो मैं फिर से एक ही त्रुटि मिलती है।

क्या मैं क्या करना चाहते toButterfly में स्थानांतरित करने की की वापसी पता, और फिर बाद में Butterfly के तर्क के रूप में उपयोग किया जाता है 'जब main() में butterflyWithBigResource निर्माण रों चाल निर्माता ButterflytoButterfly विधि में निर्माण के लिए है। क्या ऐसा करने का कोई तरीका है?

+0

Btw, कोई कॉपी-निर्माता के साथ एक वस्तु वापस जाने के लिए, आप copy- का उपयोग करेंगे सूची-प्रारंभिकरण: 'वापसी {std :: move (bigRes हमारा)} ' – 0x499602D2

उत्तर

7

जब आप स्पष्ट रूप से default और delete प्रतिलिपि बनाने वाले दोनों पंक्तियों पर टिप्पणी करते हैं, तो संकलक आपके लिए एक चालक कन्स्ट्रक्टर (और असाइनमेंट ऑपरेटर को स्थानांतरित करने) के लिए नि: शुल्क रूप से उत्पन्न करने के लिए स्वतंत्र है।

प्रतिलिपि default आईएनजी या delete कॉपी कन्स्ट्रक्टर में, आप चालक कन्स्ट्रक्टर की अंतर्निहित पीढ़ी को दबाते हैं।

N3337 से, §12.8/9[class.copy]

एक वर्ग X की परिभाषा को स्पष्ट रूप से एक कदम निर्माता की घोषणा नहीं करता है, एक परोक्ष रूप चूक घोषित किया जाएगा यदि और
केवल तभी - ...

- X एक उपयोगकर्ता के घोषित प्रतिलिपि निर्माता,
नहीं है

जब चालक कन्स्ट्रक्टर अब उत्पन्न नहीं होता है, तो toButterfly() से वापसी मान की प्रतिलिपि बनाई जानी चाहिए, लेकिन यह इस पर ध्यान दिए बिना कि आपने कॉपी कन्स्ट्रक्टर को डिफॉल्ट या हटा दिया है या नहीं।

मामले ऐसे हैं जिनमें प्रतिलिपि निर्माता default में, संकलक unique_ptr डेटा सदस्य की उपस्थिति (जो copyable नहीं है) की वजह से एक डिफ़ॉल्ट प्रतिलिपि निर्माता कार्यान्वयन उत्पन्न करने में असमर्थ है।

जब आप delete कॉपी कन्स्ट्रक्टर, अगर इसे ओवरलोड रिज़ॉल्यूशन के माध्यम से चुना जाता है, तो यह एक त्रुटि है।


आप स्पष्ट रूप से के बाद से प्रति निर्माता नष्ट करने के लिए नहीं होना चाहिए जैसा कि ऊपर बताया, unique_ptr डेटा सदस्य की उपस्थिति परोक्ष इसे हटा देता है, लेकिन यदि आप ऐसा करना चाहते हैं, तो आप भी करने की आवश्यकता होगी स्पष्ट रूप से (और इस कदम असाइनमेंट ऑपरेटर, अगर आप काम करने के लिए काम ले जाना चाहते हैं) इस कदम निर्माता डिफ़ॉल्ट

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

Live demo

+0

ओह ठीक है कि यह आसान था। –

+0

यह तय किया गया। मेरे असली कोड में मेरे पास वर्चुअल ~ सी() = डिफ़ॉल्ट था; '। –

+1

@NowIGetToLearnWhatAHeadIs * - 'X' में उपयोगकर्ता द्वारा घोषित विनाशक नहीं है * उपरोक्त सूची में चौथी गोली है :) – Praetorian

संबंधित मुद्दे