2014-05-18 8 views
10

std::unique_ptr किसी हटाए प्रतिलिपि निर्माता, जिसका मतलब है कि अगर आप एक डेटा सदस्य के रूप में अपनी कक्षा Foo में एक unique_ptr है तो आप Foo और मैन्युअल रूप से गहरे प्रतिलिपि के लिए अपनी प्रति निर्माता लिखना चाहिए है कि सदस्य (भले ही कंपाइलर से उत्पन्न प्रतिलिपि निर्माता अन्य सभी सदस्यों के लिए ठीक होगा)।ऑटो क्लोनिंग unique_ptr

पॉलिमॉर्फिक तरीके से कॉपी करने में सक्षम होने के लिए, clone() विधि पैटर्न का उपयोग किया जा सकता है।

class Base { 
    virtual std::unique_ptr<Base> clone() = 0; 
}; 

फू इस तरह दिखता है अब: चलो हमारे वस्तुओं इस तरह एक क्लोन विधि है मान लेते हैं

class Foo { 
public: 
    ... 
    Foo(Foo const& other) 
     : b(other.b->clone()) 
     , // init 10 more members that could otherwise be auto-copied just fine 
      // with the automatically generated copy constructor 
    {} 
    ... 

private: 
    std::unique_ptr<Base> b; 
    //10 more data members 

}; 

अब, मैं ऑटो क्लोन Foo::b करने के लिए एक रास्ता मिल गया, unique_ptr पर एक आवरण लिख कर कि clone पर कॉल करके कॉपी कन्स्ट्रक्टर और असाइनमेंट को परिभाषित करता है।

template <typename T> 
class auto_cloned_unique_ptr 
{ 
private: 
    std::unique_ptr<T> up; 

public: 
    // copy constructor 
    auto_cloned_unique_ptr(auto_cloned_unique_ptr<T> const& other) 
     : up(other.up->clone()) {} 

    // copy assignment 
    auto_cloned_unique_ptr<T>& operator =(auto_cloned_unique_ptr<T> const& other) 
    { 
     this->up = other.up->clone(); 
     return *this; 
    } 

    auto_cloned_unique_ptr(std::unique_ptr<T> _up) 
     : up(std::move(_up)) {} 

    // Delegate everything else to unique_ptr 
    auto_cloned_unique_ptr(auto_cloned_unique_ptr<T>&& other) 
     : up(std::move(other.up)) {} 

    auto_cloned_unique_ptr<T>& operator =(auto_cloned_unique_ptr<T>&& other) 
    { 
     this->up = std::move(other.up); 
     return *this; 
    } 

    auto operator *() const {return *up;} 
    auto operator->() const {return up.operator->();} 
    auto get() -> const {return up.get();} 

}; 

अब अगर हम इस का उपयोग हम अपने खुद के प्रति निर्माता परिभाषित करने की जरूरत नहीं है:

class Foo2 { 
public: 
    ... 

private: 
    auto_cloned_unique_ptr<Base> b; 
    //10 more data members 

}; 

(unique_ptr पर एक गैर मानक आवरण का उपयोग कर के लिए) इस तरह के दृष्टिकोण बहुत ज्यादा पर सिकोड़ी है ?

+3

ऐसे कई प्रस्ताव हुए हैं। 'Value_ptr' के लिए खोजें, बस एक नाम देने के लिए। आम तौर पर, यह गारंटी देना मुश्किल है कि इसका उपयोग सही ढंग से किया जाता है, और इसलिए मानक में शामिल होने का अधिकार नहीं है। –

+0

वैसे, 'unique_ptr' से 'निजी' का उत्तराधिकारी क्यों नहीं है और कन्स्ट्रक्टर विरासत का उपयोग क्यों करें? – Columbo

+1

* "क्या इस तरह का दृष्टिकोण बहुत अधिक फहरा हुआ है" * एक प्रश्न है जो [कोड समीक्षा] (http://codereview.stackexchange.com) आईएमओ पर बेहतर फिट बैठता है। – dyp

उत्तर

0

यह दृष्टिकोण ठीक है, लेकिन आपको बहुत सावधान रहना चाहिए कि जब आप इरादा नहीं रखते थे तो अपनी वस्तुओं को क्लोन न करें।

इसके अलावा inherriting unique_ptr प्रदर्शन

में सुधार हो सकता से
+0

'unique_ptr' से विरासत इस मामले में कभी भी मदद नहीं करेगा, क्योंकि इसके लिए कोई खाली आधार अनुकूलन नहीं है (यह कभी खाली कक्षा नहीं है) – Justin

1

अपने दृष्टिकोण के साथ समस्या यह है कि यह एक unique_ptr के अर्थ बदल रहा है है। एक unique_ptr के बारे में महत्वपूर्ण बात यह है कि यह बताता है कि किसी ऑब्जेक्ट के स्वामी कौन है। यदि आप unique_ptr के लिए एक प्रतिलिपि निर्माता जोड़ते हैं, तो इसका क्या अर्थ है? क्या आप स्वामित्व की प्रतिलिपि बना रहे हैं? ए और बी दोनों विशिष्ट रूप से अपने बात है? इसका कोई मतलब नहीं निकलता। यदि वे स्वामित्व साझा करते हैं, तो साझा साझा स्वामित्व को इंगित करने के लिए आपको shared_ptr का उपयोग करना चाहिए। यदि आप ऑब्जेक्ट की एक प्रति का अनूठा स्वामी चाहते हैं, तो आप स्वाभाविक रूप से इंगित करेंगे कि make_unique (* pFoo) द्वारा। आधार और व्युत्पन्न वस्तुओं के साथ, मूल वस्तु रखने के पास
आभासी अद्वितीय_ptr < Foo> क्लोन() const = 0;
एक पूरी तरह से सामान्य निर्माण है। यही है, व्युत्पन्न वर्गों को पता है कि खुद को कैसे कॉपी करें ताकि वे एक कटा हुआ प्रतिलिपि न बनाएं, लेकिन वे बेस क्लास में एक अद्वितीय_पीआरआर वापस लौटाने के लिए यह इंगित करें कि आपके द्वारा उत्पादित प्रतिलिपि का स्वामित्व होगा। इन क्लोन परिचालनों के भीतर, हां, आपको व्युत्पन्न कक्षाओं के गैर-प्रतिलिपि सदस्यों को स्पष्ट रूप से संभालना होगा, इसलिए आप केवल डिफ़ॉल्ट या जेनरेट की गई प्रतिलिपि बनाने में सक्षम नहीं होंगे। आपको जवाब देने की ज़रूरत है "इस चीज को कॉपी करने का क्या अर्थ है जिसमें कॉपी नहीं किया जा सकता है?"
एक ठोस उदाहरण के रूप में, एक व्युत्पन्न वर्ग की प्रतिलिपि बनाने का क्या अर्थ होगा जिसमें म्यूटेक्स था? क्या होगा यदि यह बंद कर दिया गया था और एक और थ्रेड उस पर इंतजार कर रहा था? देखें कि सामान्य जवाब देना मुश्किल क्यों है?

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