2012-09-07 14 views
12

को सरल प्रश्न यहां हटाना: क्या आपको स्पष्ट रूप से boost::shared_ptr को हटाने की अनुमति है? क्या आपको कभी चाहिएस्पष्ट रूप से एक साझा_ptr

स्पष्ट, मेरा मतलब shared_ptr द्वारा आयोजित पॉइंटर को हटाने का मतलब नहीं है। मेरा मतलब वास्तविक shared_ptr था। मुझे पता है कि ज्यादातर लोग ऐसा नहीं करने का सुझाव देते हैं, इसलिए मैं सोच रहा था कि क्या यह स्पष्ट रूप से करना ठीक है।

+1

निश्चित रूप से आपको एक (गतिशील रूप से आवंटित) * shared_ptr * को हटाने की अनुमति है; इसकी सामग्री को हटाना एक पूरी तरह से अलग सवाल है ;-) –

+0

मुझे लगता है कि आप 'weak_ptr' की तलाश में हैं। – ybungalobill

+5

गतिशील रूप से 'shared_ptr' आवंटित करने से 'shared_ptr' का उपयोग करने के उद्देश्य को हराया जाता है। – Dan

उत्तर

2

आप इसकी संदर्भ संख्या शून्य पर नहीं कर सकते हैं, नहीं।

इस बारे में सोचें कि काम करने के लिए इसके लिए क्या आवश्यक होगा। आपको shared_ptr का उपयोग करने और इसे साफ़ करने के लिए प्रत्येक स्थान पर जाना होगा।

यदि आपने साझा पॉइंटर को हटाने और इसे शून्य पर सेट करने के लिए मजबूर किया है, तो यह एक कमजोर_प्टर की तरह होगा। हालांकि, उस shared_ptr का उपयोग कर कोड में मौजूद सभी स्थान इसके लिए तैयार नहीं हैं और एक वैध सूचक होने की उम्मीद करते हैं। उनके पास न्यूल की जांच करने का कोई कारण नहीं है, और इसलिए कोड के उन बिट्स दुर्घटनाग्रस्त हो जाएंगे।

23

आपका प्रश्न स्पष्ट नहीं है। यदि आपने shared_ptr गतिशील रूप से आवंटित किया है तो आपको निश्चित रूप से delete पर अनुमति दी जाएगी जब भी आप चाहें।

लेकिन यदि आप पूछ रहे हैं कि shared_ptr द्वारा जो भी ऑब्जेक्ट प्रबंधित किया जा रहा है, तो जवाब है ... यह निर्भर करता है। यदि shared_ptr::unique सत्य लौटाता है, तो shared_ptr::reset पर कॉल करना प्रबंधित ऑब्जेक्ट को हटा देगा। हालांकि, अगर shared_ptr::unique झूठा रिटर्न देता है, तो इसका मतलब है कि उस ऑब्जेक्ट के एक से अधिक shared_ptr साझाकरण स्वामित्व हैं। इस मामले में reset पर कॉल केवल परिणाम गणना 1 के द्वारा घटित किया जाएगा, ऑब्जेक्ट का वास्तविक विलोपन तब होगा जब अंतिम shared_ptr उस ऑब्जेक्ट को प्रबंधित करने या तो स्कोप से बाहर हो या reset हो।

संपादित करें:
आपके संपादन के बाद, ऐसा लगता है कि आप एक गतिशील रूप से आवंटित shared_ptr को हटाने के बारे में पूछ रहे हैं। कुछ इस तरह:

auto sp = new boost::shared_ptr<int>(new int(42)); 

// do something with sp 

delete sp; 

यह अनुमति दी है और अपेक्षा के अनुरूप काम करेंगे, हालांकि यह एक असामान्य उपयोग मामला होगा। एकमात्र चेतावनी यह है कि यदि sp के आवंटन और हटाने के बीच में आप एक और shared_ptr बनाते हैं जो ऑब्जेक्ट के स्वामित्व को साझा करता है, sp को हटाने से ऑब्जेक्ट को हटाने में नतीजा नहीं होगा, यह तब होगा जब ऑब्जेक्ट के संदर्भ संदर्भ 0 पर जाएं ।

4

[संपादित करें: यदि आप एक shared_ptrdelete कर सकते हैं यदि और केवल यदि यह new साथ बनाया गया था, किसी भी अन्य प्रकार के रूप में ही। मुझे नहीं लगता कि कर सकते हैं तुम क्यों new के साथ एक shared_ptr बनाने चाहते हैं, लेकिन वहाँ आप को रोकने के लिए कुछ भी नहीं है।]

ठीक है, आप delete ptr.get(); लिख सकते हैं।

ऐसा करने से अपरिभाषित व्यवहार करने के लिए लगभग अनिवार्य रूप से ले जाता है या तो जब अन्य साझा मालिकों अब हटाए वस्तु पहुँचने के लिए अपने shared_ptr उपयोग करें, या पिछले shared_ptr वस्तु को नष्ट कर दिया है, और वस्तु फिर से हट जाता है।

तो नहीं, आपको नहीं करना चाहिए।

shared_ptr के प्रयोजन के लिए एक वस्तु है कि कोई भी "व्यक्ति" सही है या जिम्मेदारी को नष्ट करना है का प्रबंधन करने, क्योंकि वहाँ स्वामित्व साझा करने दूसरों हो सकता है। तो आपको कभी भी नहीं करना चाहिए, या तो।

1

आप गिनती घटती अनुकरण करने के लिए चाहते हैं, आप इसे मैन्युअल ढेर पर तो जैसे कर सकते हैं:

int main(void) { 
    std::shared_ptr<std::string>* sp = new std::shared_ptr<std::string>(std::make_shared<std::string>(std::string("test"))); 
    std::shared_ptr<std::string>* sp2 = new std::shared_ptr<std::string>(*sp); 
    delete sp; 

    std::cout << *(*sp2) << std::endl; // test 
    return 0; 
} 

या स्टैक पर तो जैसे std::shared_ptr::reset() का उपयोग कर:

int main(void) { 
    std::shared_ptr<std::string> p = std::make_shared<std::string>(std::string("test")); 
    std::shared_ptr<std::string> p2 = p; 
    p.reset(); 

    std::cout << *p2 << std::endl; // test 
    return 0; 
} 

लेकिन यह नहीं है वह उपयोगी है।

0

कुछ हद तक दुर्लभ मामलों में स्पष्ट रूप से हटाना आसान है।

स्पष्ट रूप से हटाने के अलावा, कभी-कभी आपको एक साझा सूचक को स्पष्ट रूप से नष्ट करना होता है जब आप इसे 'हटा रहे हैं'!

सी कोड के साथ इंटरफेसिंग करते समय चीजें अजीब हो सकती हैं, एक साझा मूल्य के रूप में एक shared_ptr को गुजरती हैं।

उदाहरण मैं करने के लिए और लुआ पटकथा भाषा जो सी में लिखा है (www.lua.org) से वस्तुओं पारित करने के लिए निम्नलिखित है के लिए

static void push(lua_State *L, std::shared_ptr<T> sp) 
{ 
    if(sp == nullptr) { 
     lua_pushnil(L); 
     return; 
    } 

    // This is basically malloc from C++ point of view. 
    void *ud = lua_newuserdata(L, sizeof(std::shared_ptr<T>)); 

    // Copy constructor, bumps ref count. 
    new(ud) std::shared_ptr<T>(sp); 

    luaL_setmetatable(L, B::class_name); 
} 

तो कुछ malloc'd स्मृति में एक shared_ptr thats । इसके विपरीत यह है ... (लूआ कचरा एक वस्तु एकत्र करता है और 'मुक्त है) से पहले ही इसे बुलाया जा सकता है।

static int destroy(lua_State *L) 
{ 
    // Grab opaque pointer 
    void* ud = luaL_checkudata(L, 1, B::class_name); 

    std::shared_ptr<T> *sp = static_cast<std::shared_ptr<T>*>(ud); 

    // Explicitly called, as this was 'placement new'd 
    // Decrements the ref count 
    sp->~shared_ptr(); 

    return 0; 
} 
संबंधित मुद्दे