2012-11-01 8 views
20

पर विचार निम्नलिखित:क्या अद्वितीय_ptrs के कंटेनर के साथ emplace_back का उपयोग करना सुरक्षित है?

std::vector<std::unique_ptr<int>> ptrsToInts; 
ptrsToInts.emplace_back(new int); 

पुनः आबंटन वेक्टर में होता है और यह काम नहीं करता (std::bad_alloc फेंक), मैं "सुरक्षित" हूँ या मैं एक int रिसाव हो जाएगा तो?

सी ++ 11 23.3.6.5 [vector.modifiers]/1 का कहना है:

एक अपवाद प्रतिलिपि निर्माता के अलावा किसी और फेंक दिया जाता है, तो निर्माता, असाइनमेंट ऑपरेटर ले जाते हैं, या T की असाइनमेंट ऑपरेटर के लिए कदम या किसी भी InputIterator ऑपरेशन से कोई प्रभाव नहीं पड़ता है।

जो इंगित करता है कि यह एक संभावित समस्या है। यही है, अगर "कोई प्रभाव नहीं" है, तो unique_ptr का निर्माण कभी नहीं किया गया था, और इसलिए विनाशक व्यवहार delete पर भरोसा करेगा कि सूचक नहीं होगा। (जो संकेत दे सकता है कि emplace_backunique_ptr एस के कंटेनरों के लिए प्रतिबंधित होना चाहिए)

+1

अच्छा बिंदु। इसने मुझे 'std :: make_unique' के पक्ष में पूरी तरह से 'नए' के ​​उपयोग को छोड़ने के लिए प्रेरित किया है, ताकि मैं जान सकूं कि प्रत्येक आवंटन स्मार्ट पॉइंटर पर जाने के बाद समाप्त हो जाता है। – GManNickG

+0

मैंने इस टिप्पणी को यहां एक टिप्पणी में देखा: http://stackoverflow.com/questions/3283778/why-can-i-not-push-back-a-unique-ptr-into-a-vector/3283795#3283795 –

उत्तर

18

यदि पुनर्वितरण की आवश्यकता है और यह विफल हो जाता है, तो हाँ, आपका ऑब्जेक्ट कंटेनर में कभी नहीं गया और इस प्रकार खो जाएगा।

हालांकि, यह ध्यान दिया जाना चाहिए कि यह शुद्ध उपयोगकर्ता त्रुटि है। emplace_back को unique_ptr के कंटेनर के लिए "प्रतिबंधित" नहीं होना चाहिए, क्योंकि ऐसा करने के पूरी तरह से सुरक्षित तरीके हैं (जैसे reserve पहले स्थान पर आईएनजी, तो आप जानते हैं कि यह हमेशा वहां रहेगा)। साथ ही, आप पूरे unique_ptr एस में पारित कर सकते हैं, क्योंकि यह एक चालक कन्स्ट्रक्टर का उपयोग करने में पूरी तरह से सक्षम है।

तो वास्तव में, यह आपकी गलती है कि आप आरएआईआई ऑब्जेक्ट में अपने गैर-आरएआईआई ऑब्जेक्ट (int*) को ठीक से लपेटने के लिए सही नहीं हैं, जहां आप अपवाद फेंक सकते हैं।

+2

आह - लेकिन ऑब्जेक्ट ने इसे कभी नहीं बनाया। प्रतिस्थापन ऑब्जेक्ट को वेक्टर मेमोरी ब्लॉक के अंदर ही स्थान बनाता है। क्या हो रहा है एक सूचक है, न कि 'unique_ptr'। निश्चित रूप से, सूचक नष्ट हो गया है, लेकिन क्या मुझे गारंटी है कि 'unique_ptr' का विनाशक सूचक चलाता है और हटा देता है? –

+0

दरअसल तथ्य यह है कि 'emplace' अपवाद के लिए नो-ऑप है बल्कि 'int' को ठीक से 'हटाए' नहीं मिल रहा है, क्योंकि इसका आवंटन 'emplace'' के बाहर पूरी तरह से होता है, जबकि निर्माण (deallocating) स्मार्ट सूचक अंदर होता है। –

+1

एआरएम, यहां से "गलती" होने की आवश्यकता कब है? ऐसा करने के लिए "पूरी तरह से सुरक्षित" तरीके होने के नाते, निश्चित रूप से, ऐसा करने के लिए "सुरक्षित" तरीके हैं। लेकिन अगर आप एक चालक कन्स्ट्रक्टर का उपयोग करने के लिए मजबूर करते हैं तो आप इसके बजाय 'push_back' का उपयोग कर सकते हैं, क्योंकि यह सभी मामलों में सही व्यवहार को लागू करता है। –

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