2015-04-15 19 views
26

मैं एक समारोह के रूप में परिभाषित किया गया है के साथ ले जाने के इस प्रकार है:एसटीडी का उपयोग करते हुए :: std :: shared_ptr

void foo(std::shared_ptr<X> x) { ... }; 

अगर मैं X करने के लिए एक साझा ptr की घोषणा:

std::shared_ptr<X> sourcePtr(new X(...)); 

मैं तो foo के रूप में कॉल कर सकते हैं इस प्रकार है:

foo(std::move(sourcePtr)); 

या

+०१२३५१६४१०
foo(sourcePtr); 

मैं समझता हूँ कि अगर मैं पहला विकल्प तो का उपयोग sourcePtr अशक्त हो जाता है। क्या यह संदर्भ संख्या को बढ़ने से भी रोकता है?

हैं कि कोई फर्क नहीं पड़ता है, जो विकल्प मैं पसंद करना चाहिए? क्या मुझे ऐसा निर्णय लेने पर किसी और चीज पर विचार करना चाहिए?

+5

संक्षेप में, आपको लगता है कि संदर्भ काउंटर में सही वृद्धि नहीं की जाएगी कर रहे हैं। हालांकि मैं इसके लिए एक व्यावहारिक उपयोग को देखने के लिए, जब तक आप सूचक आप पारित खाली किया जाना चाहिए, जिस स्थिति में आप 'बजाय प्रयोग किया जा सकता था std :: unique_ptr' बाध्य करना चाहते हैं असफल।आपको वास्तव में नए पॉइंट पॉइंटर्स को * पॉइंटर * के रूप में नहीं देखना चाहिए, इसके बजाय आपको उन्हें * संसाधन स्वामित्व * परिप्रेक्ष्य से देखना चाहिए। क्या संसाधन का संसाधन केवल एक इकाई ('std :: unique_ptr') या एकाधिक इकाइयों (' std :: shared_ptr') द्वारा किया जा सकता है। –

+0

यह बहुत ही समान प्रश्न है, हालांकि मुझे यकीन नहीं है कि क्या सही डुप्लिकेट है: http://stackoverflow.com/questions/10953325/should-i-stdmove-a-shared-ptr-in-a-move-constructor। यह सवाल कार्य करने के लिए तर्क पारित करने के बारे में है - इस तरह से अलग ... – PiotrNycz

+0

@ जोचिमपिलबोर्ग यह कुछ परीक्षण कोड का एक सरल उदाहरण है, जो पूरी कहानी नहीं बताता है लेकिन मुझे विशेष रूप से उस प्रश्न पर ध्यान केंद्रित करने की अनुमति देता है जिसे मैं जानना चाहता हूं । 'Foo' को मेरे एप्लिकेशन में 'shared_ptr' लेने की आवश्यकता है लेकिन कॉल कोड के बाद परीक्षण कोड को' SourcePtr' की आवश्यकता नहीं है। – ksl

उत्तर

30

हाँ, आप समारोह में साझा पॉइंटर को चलाने, तो:

  1. मूल sourcePtr अशक्त हो जाएगा, और

  2. संदर्भ गिनती संशोधित नहीं होती है।

आप जानते हैं कि तुम अब, समारोह कॉल के बाद sourcePtr का मूल्य की आवश्यकता होगी यह समारोह में आगे बढ़ एक मामूली अनुकूलन है, के रूप में यह एक परमाणु वेतन वृद्धि (और बाद में घटती बचत होती है, तो जब sourcePtr गुंजाइश से बाहर चला जाता है)।

हालांकि, सावधान रहें कि पहचानकर्ता sourcePtr अभी भी शेष दायरे के लिए मान्य है, बस यह एक शून्य सूचक है। जिसका अर्थ यह है कि यदि आप इसे स्थानांतरित करने के बाद उपयोग करते हैं तो संकलक शिकायत नहीं करेगा, लेकिन यदि आप भूल जाते हैं कि इसे स्थानांतरित किया गया था, तो आप सभी संभावनाओं को कमजोर कर देंगे। मैं इस "के अनुकूलन" move एक बहुत का उपयोग करते हैं, और मैं भी यह द्वारा कई बार काट लिया गया है: और अधिक कार्यक्षमता समारोह में जोड़ा जाता है, और आप move पूर्ववत करने के लिए भूल जाते हैं, तो आप एक अच्छा दुर्घटना मिलता है।

तो चलती जब आप अब उसे एक मामूली अनुकूलन एक मामूली रखरखाव बोझ के साथ मिलकर है की जरूरत है। वजन घटाने के लिए आप पर निर्भर है जो आपके मामले में अधिक महत्वपूर्ण है।

ऊपर मान लिया गया कोड जो वास्तव में करने के लिए foo इसकी घोषणा और अंतिम कॉल के बीच sourcePtr का उपयोग करता है (धन्यवाद यह ओर इशारा करते हुए के लिए @WhozCraig करने के लिए) नहीं है।

foo(std::make_shared<X>(...)); 

इस तरह, आप परमाणु आपरेशन के एक ही राशि, और बचाने आप की जरूरत नहीं है: अगर वहाँ नहीं है, आप ज्यादा से बेहतर सही कॉल स्थल पर सूचक बनाने होगा एक संभावित खतरनाक खाली साझा सूचक चारों ओर झूठ बोल रहा है।

+3

मुझे लगता है कि यह व्यर्थ है। यही कारण है कि 'shared_ptr' पेश किया गया था - न केवल सुरक्षा के कारण (स्मृति रिसाव से बचने के मामले में), बल्कि यह भी कि महंगे-प्रति-प्रति वस्तुओं को सुरक्षित रूप से (लगभग) मुक्त के लिए साझा किया जा सकता है। एकल परमाणु ओप अनुकूलित करना समय की बर्बादी की तरह लगता है। –

+5

बस अपनी खुद की स्पष्टता के लिए, यदि निर्माण और आविष्कार वास्तव में उदाहरण के रूप में सरल थे (और यह नहीं हो सकता है), तो 'foo (std :: make_shared (...)) नहीं होगा;' इसे पूरा करें एक त्याग छोड़ने के बिना चीज (और जैसा कि आप इंगित करते हैं, संभावित रूप से जोखिम भरा) 'std :: shared_ptr 'खोल खोलने के आसपास? निश्चित रूप से यह विकल्प नहीं है यदि मध्यवर्ती 'SourcePtr-> सदस्य()' कोड (आवंटन और कॉल) के बीच कोड है। लेकिन अगर नहीं है? – WhozCraig

+0

@WhozCraig अच्छा बिंदु, मैं इसे उत्तर में जोड़ दूंगा। – Angew

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