2012-03-20 5 views
5

निम्नलिखित कार्यक्रम दुर्घटनाओं में ही करने के लिए एक std :: shared_ptr रीसेट होता है:क्या होगा यदि मैं एक बुरा glibc डबल मुक्त त्रुटि के साथ

#include <iostream> 
#include <memory> 

class foo { 
public: 
    foo() 
    { 
     std::cout << "foo constructed" << std::endl; 
    } 

    ~foo() 
    { 
     std::cout << "foo destructed" << std::endl; 
    } 
}; 

int main() { 
    auto f = std::make_shared<foo>(); 
    std::cout << "Before reset" << std::endl; 
    f.reset(f.get()); 
    std::cout << "After reset" << std::endl; 
    return 0; 
} 

इस से मैं निम्नलिखित निर्गम (glibc त्रुटि के बाद):

foo constructed 
Before reset 
foo destructed 
After reset 
foo destructed 

तो जाहिर है इस मामले में वस्तु दो बार नष्ट हो जाती है। एक बार रीसेट द्वारा और एक बार std::shared_ptr गुंजाइश से बाहर जा रहा है। यह वास्तव में मैं अपेक्षा करता था।

cppreference पर फिर भी मैं निम्न पाठ (http://en.cppreference.com/w/cpp/memory/shared_ptr/reset में पाया जाता है) को खोजने:

If *this already owns an object and it is the last shared_ptr owning it, the object is destroyed through the owned deleter, unless ptr is a pointer to it.

मेरी राय यह वास्तव में कहते हैं, उस वस्तु मेरे उदाहरण के रूप में नष्ट नहीं किया जाना चाहिए। काफी आश्चर्यजनक, लेकिन अगर मानक ऐसा कहता है। क्या मैं इसे किसी भी तरह गलत तरीके से पढ़ रहा हूं, या std::shared_ptr का कार्यान्वयन है, क्या मैं मानक के अनुरूप नहीं हूं?

जो लोग पूछने कारण है कि मैं यह कर रहा हूं के लिए:

मैं वर्तमान में यह पता लगाने की कैसे अस्थायी रूप से new और new[] द्वारा बनाई गई वस्तुओं के लिए नंगे संकेत प्रबंधन करने के लिए कोशिश कर रहा हूँ। विचार को नो-ऑप डिलीटर के साथ हटाए जाने के लिए std::shared_ptr::reset() का उपयोग करना है। वैकल्पिक कोड को try { stuff() } catch(...) { delete x; throw;} ब्लॉक के साथ लपेटना है।

+2

'F.Reset (f.get()) (हालांकि, जबकि std::shared_ptr<T>std::unique_ptr<T> से Deleter उठाता है, तब भी आप जैसा कि आप शायद std::unique_ptr<T[]> से std::shared_ptr<T*> चाहते सरणी मामले में विशेष उपचार की जरूरत है।)' तुम क्यों होगा * कभी * यह करना चाहते हैं? यदि आपके पास अस्थायी "ऑब्जेक्ट्स के लिए नंगे पॉइंटर्स" हैं, तो आपको उन्हें * हटा नहीं देना चाहिए। आपको केवल उन्हीं चीज़ों को हटाना चाहिए जो आपके पास हैं *, और आपके पास 'shared_ptr :: get' से प्राप्त होने वाली चीज़ों का स्वामित्व नहीं है। –

+0

@ निकोलबोलस: आसान उत्तर: क्योंकि cppreference ने सुझाव दिया कि यह अन्य मामलों की तुलना में अलग-अलग संभाला जाएगा। ऐसा लगता है कि जानकारी गलत है। मैं cppreference पर इस पर एक चर्चा शुरू करूंगा। – LiKao

+0

यह केवल बताता है कि आपने सोचा कि यह क्यों काम करेगा। यह स्पष्ट नहीं करता कि आपने क्यों सोचा कि यह एक अच्छा विचार होगा, चाहे वह काम करता है या नहीं। आप क्या करने की कोशिश कर रहे हैं * आपको * चाहिए? –

उत्तर

7

reset की है कि अधिभार के लिए विनिर्देश 20.7.2.2.4 shared_ptr संशोधक में दी गई है [util.smartptr.shared.mod], पैरा 3 (n3290 से):

template<class Y> void reset(Y* p); 

Effects: Equivalent to shared_ptr(p).swap(*this) .

आप देख सकते हैं, कि shared_ptr(p) निर्माण उस p के लिए नए डिलीटर के साथ एक नई गिनती बनाता है, इसलिए कुछ भी अच्छा नहीं हो सकता है। std::shared_ptr<T>::get को सख्ती से पर्यवेक्षक के रूप में सोचने के लिए वास्तव में सबसे अच्छा है, और जीवन भर प्रबंधन से निपटने के लिए इसका उपयोग करना एक बयान है कि कुछ गलत चल रहा है।

दूसरी ओर, std::unique_ptr<T> में release है, जो आपको तुरंत कदम उठाने और तत्काल के लिए स्वामित्व के साथ सौदा करने की आवश्यकता होती है। शायद आप std::unique_ptr<T> का उपयोग करने के लिए अपना डिज़ाइन बदल सकते हैं? अगर आपको अंततः std::shared_ptr<T> बनाना है तो इसे हमेशा संभव बनाना है।

+0

ठीक है, मैं यही उम्मीद करता था, क्या मैंने cppreference पर यह निश्चित नहीं देखा था। मैं इसे बदलने के लिए वहां एक चर्चा शुरू करूंगा। – LiKao

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