2015-03-18 7 views
5

के स्वामित्व को स्थानांतरित करने के लिए कन्स्ट्रक्टर की प्रतिलिपि बनाएँ मुझे प्रतिलिपि बनाने वाले ऑब्जेक्ट के एक अद्वितीय_ptr सदस्य के स्वामित्व को स्थानांतरित करने की आवश्यकता है।एक अद्वितीय_ptr

class C{ 
    // C class stuff  
}; 

class A{ 
public: 
    public A(); 
    public A(const A& a); 
private: 
    std::unique_ptr<C> c_; 
} 

class B{ 

public: 

    B(const A& b) : a_(a){} 

private: 
    A a_; 


}; 

मैं A के लिए प्रतिलिपि निर्माता कैसे लागू करना चाहिए: स्थिति इस प्रकार है?

+10

तो जब आप एक प्रतिलिपि बनाते हैं तो आप मूल अमान्य बनाना चाहते हैं? मैं कॉपी कन्स्ट्रक्टर को हटाने और कक्षा को केवल चलने योग्य बनाने का सुझाव दूंगा। – NathanOliver

+0

यदि मूल के साथ आप मूल वस्तु का मतलब है हां यह कक्षा बी के सदस्य के रूप में "हस्तांतरण" होना चाहिए। क्या आप इसका उदाहरण प्रदान कर सकते हैं? – gcswoosh

+3

@ गैब्रिलेक्सवोश [टैग: मूव-सेमेन्टिक्स] टैग पर प्रश्न/उत्तर पढ़ने में कुछ समय बिताएं। –

उत्तर

5

आपका इरादा या दृष्टिकोण गलत है, मुझे लगता है।

कॉपी-निर्माता तर्क का एक प्रतिलिपि बनाने के लिए लिए है, लेकिन unique_ptr के बाद से एकमात्र स्वामित्व एक इसकी एक प्रति नहीं कर सकते हैं बनाए रखता है। आप वास्तव में अद्वितीय_ptr सदस्य mutable बना सकते हैं और उसके बाद संसाधन को कॉपी-कन्स्ट्रक्टर में ले जा सकते हैं लेकिन यह बिल्कुल पागल हो जाएगा (यह std::auto_ptr करता है और यही कारण है कि इसे बहिष्कृत किया गया है)।

  • ए और बी के क़दम-निर्माता जोड़ने (+ कॉपी-निर्माता नष्ट कर दिया बनाना)
  • स्विच unique_ptr से shared_ptr लिए, लेकिन केवल तभी सी वास्तव में करने के लिए है:

    इसलिए या तो आप की जरूरत है साझा किया जा

वहाँ भी एक तीसरा विकल्प, वस्तु की एक प्रति एक की कॉपी-निर्माता में unique_ptr द्वारा की ओर इशारा करने के लिए है जो, यानी है:

A::A(const A& a) : c_(std::unique_ptr<C>(a.c_ ? new C(*a.c_) : nullptr)) { 
} 
+0

मैं इरादा गलत नहीं कहूंगा। इंटरफ़ेस मॉडलिंग को एक नियमित प्रकार * बनाने के लिए बिल्कुल ठीक है, जो लपेटा हुआ प्रकार स्वाभाविक रूप से खुलासा नहीं कर सकता है। – mavam

+0

मैं आपसे सहमत नहीं हूं। आप एक ऑब्जेक्ट की प्रतिलिपि बना सकते हैं जिसमें unique_ptr है। उदाहरण के लिए, मैं लिंक्डलिस्ट क्लास को कार्यान्वित कर सकता हूं जो अद्वितीय तत्व को अगले तत्व के सूचक के रूप में रखता है। क्या इसका मतलब है कि मैं पसंद की गई सूची की प्रतिलिपि नहीं बना सकता या नहीं? मैं लिंक्ड सूची को स्वयं कॉपी करना चाहता हूं और प्रतिलिपि ऑब्जेक्ट –

+4

@ डेविडहाइम के अद्वितीय_ptr में उस प्रति को सहेजना चाहूंगा, लेकिन ओपी कॉपी-कन्स्ट्रक्टर में स्वामित्व को स्थानांतरित करना चाहता है - यही सवाल है कि यह शीर्षक है। मैं इसे गलत दृष्टिकोण मानता हूं। –

3

तकनीकी तौर पर,

को

एक प्रति निर्माता कि भी वस्तु का एक unique_ptr सदस्य के स्वामित्व का हस्तांतरण प्रतिलिपि बनाई जा रही

तुम सिर्फ यह कर सकते हैं लिखें:

class Bad 
{ 
private: 
    unique_ptr<int> p_; 
public: 
    Bad(): p_(new int(666)) {} 
    Bad(Bad& other) 
     : p_(move(other.p_)) 
    {} 
}; 

क्योंकि एक कॉपी निर्माता के पास यह हस्ताक्षर भी हो सकता है, plu अधिक पारंपरिक Bad(const Bad&) के अलावा, दो और अधिक।

मैंने उस श्रेणी को Bad नाम दिया क्योंकि यह वास्तव में बुरा है, यह किसी और के कोड के छेड़छाड़ को छोड़कर इस चीज़ को करने के लिए समझ में नहीं आता है।

एक प्रति निर्माता है कि नकल नहीं करता है के बजाय

,

  • एक चाल निर्माता कि चाल, या

  • एक साधारण प्रतिलिपि निर्माता को लागू लागू कि प्रतियां, या

  • क्लास डिज़ाइन को उदाहरण के लिए बदलें साझा स्वामित्व

4

जाहिर है आप न सिर्फ std::unique_ptr एस के एक काम के रूप में अपने असाइनमेंट ऑपरेटर हटा दी जाती है कर सकते हैं। यह प्रोग्रामर को अपने इच्छित व्यवहार को परिभाषित करने के लिए मजबूर करना है।

  1. नया आइटम मूल आइटम को अमान्य कर c_ का स्वामित्व लेता है।
  2. नया आइटम मूल आइटम वैधता को बनाए रखने, c_ की एक प्रति बनाता है।
  3. नया आइटम c_ का स्वामित्व साझा करता है ताकि दोनों नए और मूल आइटम एक ही ऑब्जेक्ट को संदर्भित कर सकें।

में मामला 1 क्या आप देख रहे हैं एक कदम निर्माता है, और डिफ़ॉल्ट चाल निर्माता से कार्य करेंगे। तो अगर आप किसी भी कोड लिखने की जरूरत नहीं है, तो आप सिर्फ कर सकते हैं:

A temp; 
A foo(std::move(temp)); 

ध्यान दें कि temp के बाद यह ले जाया जाता है अमान्य है। A में इस परिभाषित आप कर सकते हैं के बाद

A(const A& a):c_(new C(*(a.c_))){} 

:

में मामला 2 आप मूल के c_ की एक प्रतिलिपि बनाने के लिए A के लिए एक कस्टम प्रतिलिपि निर्माता जोड़ने की आवश्यकता होगी

A foo(A()); 

ध्यान दें कि यह C की कॉपी कन्स्ट्रक्टर पर कार्यात्मक होने पर निर्भर करता है।

मामले 3 में आप मूलरूप से एक std::shared_ptr उपयोग करने के लिए एक std::unique_ptr का उपयोग करने से A को बदलना होगा, तो c_ की परिभाषा बन गयी:

std::shared_ptr<C> c_; 

c_ का आपका निर्माण के समान होगा c_ के std::unique_ptr संस्करण के लिए आप पहले से ही क्या उपयोग कर रहे हैं। तो बस डिफ़ॉल्ट कार्यान्वयन का उपयोग कर आप कर सकता है:

A foo; 
A bar(foo); 

और अब foo और एक ही C वस्तु को bar बिंदु है, और यह के स्वामित्व को साझा करें। यह साझा ऑब्जेक्ट तब तक नहीं हटाया जाएगा जब तक कि सभी shared_ptr के संदर्भ में इसे हटा दिया गया हो।

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