2011-11-23 19 views
20

के कंटेनर पर इटरेटिंग एक कंटेनर से स्वामित्व को दूर किए बिना किसी कंटेनर (एक इटरेटर के माध्यम से) के अद्वितीय_ptr तत्वों को कैसे एक्सेस करता है? जब किसी को कंटेनर में किसी तत्व के लिए पुनरावर्तक प्राप्त होता है तो वह कंटेनर के साथ तत्व स्वामित्व है? अनन्य_प्टर तक पहुंच प्राप्त करने के लिए जब कोई इटरेटर को अस्वीकार करता है तो कैसा होता है? क्या यह unique_ptr का एक अंतर्निहित कदम करता है?unique_ptr के

मुझे लगता है कि मैं एक कंटेनर (मूल्य से नहीं) में तत्वों को स्टोर करने की आवश्यकता होने पर साझा_ptr का उपयोग कर रहा हूं, भले ही कंटेनर अवधारणात्मक रूप से तत्वों का मालिक हो और अन्य कोड बस कंटेनर में तत्वों में हेरफेर करना चाहता हो, क्योंकि मैं मैं वास्तव में बिना किसी स्वामित्व के कंटेनर में अद्वितीय_ptr तत्वों तक पहुंचने में सक्षम नहीं होने से डरता हूं।

कोई अंतर्दृष्टि?

उत्तर

13

जब तक आप unique_ptr की एक प्रति बनाने की कोशिश नहीं करते हैं, तो आप इसका उपयोग कर सकते हैं। पॉइंटर के मूल्य पर पहुंचने के लिए आपको इटेटरेटर को "डबल ड्रेफरेंस" करना होगा, जैसा आपको shared_ptr के साथ करना होगा।

Ptr p = v[0]; 

तो आप संकलन समय पर बाहर मिल जाएगा:

#include <vector> 
#include <memory> 
#include <iostream> 

template <class C> 
void 
display(const C& c) 
{ 
    std::cout << '{'; 
    if (!c.empty()) 
     std::cout << *c.front(); 
    for (auto i = std::next(c.begin()); i != c.end(); ++i) 
     std::cout << ", " << **i; 
    std::cout << "}\n"; 
} 

int main() 
{ 
    typedef std::unique_ptr<int> Ptr; 
    std::vector<Ptr> v; 
    for (int i = 1; i <= 5; ++i) 
     v.push_back(Ptr(new int(i))); 
    display(v); 
    for (auto i = v.begin(); i != v.end(); ++i) 
     **i += 2; 
    display(v); 
} 

यदि आप करते हैं (गलती से) unique_ptr की एक प्रतिलिपि बनाने: यहाँ एक संक्षिप्त उदाहरण है। यह रन टाइम त्रुटि का कारण नहीं बनता है। आपका उपयोग मामला है क्यों container<unique_ptr<T>> बनाया गया था। चीजें सिर्फ काम करनी चाहिए, और यदि वे नहीं करते हैं, तो समस्या रन समय के बजाय संकलन समय पर दिखाई देती है। तो कोड दूर करें, और यदि आप संकलन समय त्रुटि को समझ नहीं पाते हैं, तो यहां एक और प्रश्न पूछें।

+0

ठीक है मुझे लगता है कि मेरे लिए चीजों को स्पष्ट करता है। मैं एक लैम्ब्डा के साथ नए for_each फ़ंक्शन का उपयोग करने की आदत में रहा हूं जिसका पैरामीटर मान द्वारा पारित तत्व है, संदर्भ के अनुसार नहीं, लेकिन मुझे लगता है कि मुझे इसे अद्वितीय_ptr तत्वों के संदर्भ में बनाना होगा यदि मैं किसी प्रयास से बचना चाहता हूं प्रतिलिपि/चालें। अनुलेख अगर मैं एक बार इटरेटर को अस्वीकार करता हूं, और उस परिणाम का संदर्भ लेता हूं, तो मुझे लगता है कि यह एक प्रयास की गई प्रतिलिपि से बचाता है? मेरा मतलब है: 'के लिए (कंटेनर :: iterator it = container.begin(); it! = Container.end(); यह ++) { unique_ptr और तत्व = &*it; // कोई प्रयास प्रतिलिपि नहीं है? } ' धन्यवाद हॉवर्ड, बीटीडब्ल्यू। –

+0

हाँ, मुझे लगता है कि ठीक काम करना चाहिए। यद्यपि आपके पास अपने कोड में अतिरिक्त '&' है। लेकिन संकलक आपको बताएगा कि कहां है। –

+0

आपको इसे किसी को अस्वीकार करने में सक्षम होना चाहिए: blah और element = ** it; अभी भी एक प्रतिलिपि के बिना, मुझे लगता है। (शायद अधिक उपयोगी।) –

32
auto साथ

और सीमा के आधार पर के लिए-छोरों की सी ++ 11 इस अपेक्षाकृत सुरुचिपूर्ण हो जाता है:

std::vector< std::unique_ptr<YourClass>> pointers; 
for(auto&& pointer : pointers) { 
    pointer->functionOfYourClass(); 
} 

संदर्भ &std::unique_ptr को कॉपी करने से बचा जाता है और आप अपसंदर्भन बिना uniqe_ptr उपयोग कर सकते हैं।

+0

क्या किसी को पता है कि इस मामले में 'ऑटो और' और 'ऑटो &&' का उपयोग करने में कोई अंतर है या नहीं? यह संदर्भ डबल और http://en.cppreference.com/w/cpp/language/range-for का सुझाव देता है, दोनों – austinmarton

+0

संकलित करने के लिए प्रतीत होते हैं। मैंने पाया [यह लिंक] (http://en.cppreference.com/w/cpp/language/auto) (स्पष्टीकरण/1 देखें) जो बताता है कि 'ऑटो &&' प्रारंभकर्ता के आधार पर अंतराल और रावल्यू के रूप में काम कर सकता है। मैं तदनुसार उदाहरण अनुकूलित करता हूं। – Pascal

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