2013-10-16 3 views
7

इसे सुरक्षितvector.emplace_back (नया MyPointer) का उपयोग करने के लिए सुरक्षित; वेक्टर के अंदर विफलता लीक मेमोरी के लिए नेतृत्व कर सकता है?

vector.emplace_back(new MyPointer()); 

या एक अपवाद फेंका जा सकता था या वेक्टर कारण स्मृति रिसाव के अंदर कुछ विफलता का उपयोग करने के है?

बेहतर होगा निम्नलिखित है, जहां आप पहले एक अस्थायी unique_ptr में सूचक डाल के कुछ फार्म करने के लिए।

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

तो यदि कोई वेक्टर विफलता होती है तो अस्थायी unique_ptr अभी भी स्मृति को साफ़ कर देगा?

+0

मेरा सुझाव है 'std :: एक बार make_unique' कुछ सी ++ 14 समर्थन उपलब्ध अपनी खुद की अगर नहीं है या। – chris

उत्तर

11

यह सुरक्षित नहीं है और यदि आप पहले संस्करण का उपयोग करते हैं तो मेमोरी रिसाव बनाएंगे। documentation कहता है कि यदि कोई अपवाद फेंक दिया जाता है, तो emplace पर कॉल का कोई प्रभाव नहीं पड़ता है - जिसका अर्थ है कि आपके द्वारा पारित सादा सूचक कभी नहीं हटाया जाता है।

आप

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

या सी ++ 14 के साथ उपयोग कर सकते हैं आप

vector.emplace_back(std::make_unique<MyPointer>()); 

उपयोग कर सकते हैं या, यदि सी ++ 14 अभी उपलब्ध नहीं है, बस make_unique के अपने स्वयं के संस्करण रोल। आप इसे here देख सकते हैं।

+3

आपको उपरोक्त के साथ 'वेक्टर' के प्रकार को बदलने की भी आवश्यकता है। यदि यह अक्षम है, तो आप जोड़े गए तत्व को स्मार्ट पॉइंटर में बाहर स्टोर कर सकते हैं, इसे जोड़ सकते हैं, फिर यह काम करने पर अलग हो सकता है। – Yakk

+0

आपका मतलब 'सी ++ 14' के बजाय 'सी ++ 11' है? – fnc12

+2

@ fnc12 नहीं, मेरा मतलब सी ++ 14 था। ['std :: make_unique'] (http://en.cppreference.com/w/cpp/memory/unique_ptr/make_unique) सी ++ 11 में उपलब्ध/मानकीकृत नहीं था। –

2

नहीं है, पहले परिदृश्य सुरक्षित नहीं है और स्मृति रिसाव हो जाएगा अगर vector एक अपवाद फेंकता है।

दूसरा परिदृश्य संकलित नहीं होगा, क्योंकि std::unique_ptr<T> को T* में स्पष्ट रूप से परिवर्तित नहीं किया जा सकता है। यहां तक ​​कि अगर यह हो सकता है, तो यह परिदृश्य पहले की तुलना में तर्कसंगत रूप से खराब है, क्योंकि यह आपके वेक्टर में पॉइंटर जोड़ देगा, फिर ऑब्जेक्ट को तुरंत इंगित कर देगा। आपको एक लटकने वाले सूचक वाले वेक्टर के साथ छोड़ा जाएगा।

अपने std::vector के प्रकार को बदलने के बिना (जो मुझे लगता है std::vector<MyPointer*> है) इस कोड अपवाद को सुरक्षित करने के दो तरीके हैं।

का उपयोग सी ++ 11:

auto ptr = std::unique_ptr<MyPointer>(new MyPointer()); 
vector.emplace_back(ptr.get()); 
ptr.release(); 

या अधिक वर्बोज़ सी ++ 03 तरीका:

MyPointer* ptr = new MyPointer(); 
try 
{ 
    vector.push_back(ptr); 
} 
catch (...) 
{ 
    delete ptr; 
    throw; 
} 

आप तो सबसे आसान तरीका है अपने std::vector<MyPointer*> का प्रकार बदलने के लिए सक्षम हैं, तो

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

या सी ++ 14 के साथ: ऊपर डैनियल फ्रे ने सुझाव दिया उन

std::vector<std::unique_ptr<MyPointer>> vector; 
vector.emplace_back(std::make_unique<MyPointer>()); 
संबंधित मुद्दे