2013-01-23 36 views
9

में धक्का देते समय std :: unique_ptr का सही उपयोग क्या है, मैं अपनी कक्षा में ऑब्जेक्ट्स के पॉइंटर्स का वेक्टर रखना चाहता हूं। इसके लिए एक विनाशक बनाने से बचने के लिए मैं std::unique_ptr का उपयोग करना चाहता था, क्योंकि वस्तुओं को मेरी कक्षा में बनाया/स्वामित्व/नष्ट कर दिया गया है, लेकिन मेरे पास एक कंपाइलर त्रुटि है जिसे मैं समझ नहीं पा रहा हूं।std :: vector

std::unique_ptr<int> createPtr(int value) 
{ 
    std::unique_ptr<int> ptr(new int(value)); 
    return ptr; 
}; 

int main() 
{ 
    std::vector<std::unique_ptr<int>> vec; 
    vec.push_back(createPtr(1)); 

    std::unique_ptr<int> ptr = createPtr(2); 
    vec.push_back(ptr);//error C2248: 'std::unique_ptr<_Ty>::unique_ptr' : cannot access private member declared in class 'std::unique_ptr<_Ty>' 
} 

क्या आप मुझे बता सकते हैं क्यों मैं इस त्रुटि मिलती है और std::unique_ptr के लिए सही उपयोग क्या है: अगली कोड मेरी समस्या के लिए एक छोटा नमूना रूप में काम करेगा?

+1

वेक्टर में मूल्यों के बजाय पॉइंटर्स को 'int' में संग्रहीत करने का क्या मतलब है? –

+0

यदि आप 'std :: unique_ptr <>' पर विचार कर रहे हैं, तो संभवतः आप * ऑब्जेक्ट्स का वेक्टर नहीं रखते हैं, लेकिन "ऑब्जेक्ट्स के पॉइंटर्स का वेक्टर"। यदि आपके पास "ऑब्जेक्ट्स का वेक्टर" था, तो विनाश स्वचालित रूप से ठीक से होगा। –

+0

@TadeuszKopec कृपया प्रश्न पढ़ें – Felics

उत्तर

12

vec.push_back() पर विचार करें। इसमें दो ओवरलोड हैं जो const std::unique_ptr<int>& या std::unique_ptr<int>&& लेते हैं। पहला अधिभार कभी भी का उपयोग नहीं किया जा सकता है। ऐसा इसलिए है क्योंकि vector<> को असाइन करने योग्य, या चलने योग्य (सी ++ 11 अतिरिक्त) की आवश्यकता होती है। 'असाइन करने योग्यता' का तात्पर्य है। push_back(const T&) कंटेनर के अंत में आने वाली मान को नए स्थान पर कॉपी (असाइन) करने की कोशिश करेगा। std::unique_ptr<> एक ऐसे संसाधन का प्रतिनिधित्व करता है जिसका स्वामित्व एक मालिक के पास है। इसे कॉपी करके (सूचक) एकाधिक मालिक मौजूद होंगे। उस unique_ptr की प्रतिलिपि की प्रतिलिपि नहीं है।

यह सब कहकर, आप केवल T&& अधिभार का उपयोग कर सकते हैं।

createPtr()std::unique_ptr<int> लौटाता है, लेकिन चूंकि यह एक अस्थायी परिणाम (फ़ंक्शन रिटर्न मान) है, इसे एक रावल्यू संदर्भ (अंतर्निहित) माना जाता है। यही कारण है कि इसका इस्तेमाल किया जा सकता है।

ptr सिर्फ एक std::unique_ptr<int> जो एक lvalue संदर्भ है (कोई फर्क नहीं पड़ता अगर आप उसके बगल में & & डाल के रूप में नामित किया गया rvalues ​​अभी भी lvalues ​​माना जाता है) है। Lvalue कभी अंततः rvalue (पूरी तरह से असुरक्षित) में परिवर्तित नहीं किया जाता है। लेकिन आप मूल रूप से संकलक को बता सकते हैं "ठीक है, आप जिस ऑब्जेक्ट को पास करते हैं उसे ले सकते हैं, और मैं वादा करता हूं कि std::move() का उपयोग करके मैं तर्क को बरकरार रखने की उम्मीद नहीं करूंगा।

std::unique_ptr<int> ptr = createPtr(2); 

अब आप वेक्टर में इसकी एक प्रति रख::

vec.push_back(ptr); 

अब आप एक ही मूल्य के साथ दो unique_ptr रों है

14

कोई एक:

vec.push_back(std::move(ptr)); 

या:

vec.emplace_back(createPtr(2)); 
+1

यह समस्या हल करता है, लेकिन क्या आप समस्या की व्याख्या कर सकते हैं? – Felics

+7

@ फ़ेलिक्स समस्या यह है कि 'unique_ptr' प्रतिलिपि निर्माण की अनुमति नहीं देता है, इसलिए 'ptr_back'' ptr' को विफल करने की कोशिश विफल हो जाती है क्योंकि यह प्रतिलिपि निर्माता को आमंत्रित करने का प्रयास करती है।हालांकि, चालक कन्स्ट्रक्टर सुलभ है, और केरेक के समाधान दोनों कॉपी कॉपी कन्स्ट्रक्टर के बजाय कहते हैं। – Praetorian

+0

@Praetorian 'emplace_back' के बारे में क्या? – 0x499602D2

2

आप एक unique_ptr है। अगर इसकी अनुमति दी गई तो यह अद्वितीय नहीं होगा।

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