2011-03-23 8 views
7

इस विषय के बारे में पहले से ही कुछ प्रश्न हैं, लेकिन मुझे अभी भी यकीन नहीं है कि क्या करना है: हमारे कोडबेस कई स्थानों पर shared_ptr का उपयोग करता है। मुझे यह मानना ​​है कि हमने इसे लिखते समय स्वामित्व को स्पष्ट रूप से परिभाषित नहीं किया है।क्या मुझे विधि में पास होने पर shared_ptr को weak_ptr में परिवर्तित करना चाहिए?

हम पहले (अप्रत्यक्ष) परिपत्र निर्भरता मैं अपने डिजाइन में गलतियों को सही करना चाहते हैं की खोज की होने के बाद

void doSomething(shared_ptr<MyClass> ptr) 
{ 
     //doSomething() is a member function of a class, but usually won't store the ptr 
     ptr->foo(); 
     ... 
} 

की तरह कुछ तरीकों की है। लेकिन मुझे बिल्कुल यकीन नहीं है कि कैसे। विधि से

void doSomething(weak_ptr<MyClass> ptr) 
{ 
     shared_ptr<MyClass> ptrShared = ptr.lock(); 
     ptrShared->foo(); 
     ... 
} 

से विधि को बदलने में कोई लाभ है?

मैं भी उलझन में हूं क्योंकि कुछ लोग कहते हैं (Google स्टाइल गाइड समेत) कि पहले स्थान पर स्वामित्व सही होना महत्वपूर्ण है (जो शायद weak_ptrs का परिचय होगा, उदाहरण के लिए ऊपर दिए गए तरीकों के साथ उदाहरण में, लेकिन हमारे पास कई सदस्य चर के लिए भी है)। अन्य कहते हैं (नीचे दिए गए लिंक देखें) कि आपको चक्रीय निर्भरताओं को तोड़ने के लिए weak_ptr का उपयोग करना चाहिए। हालांकि, उन्हें पहचानना हमेशा आसान नहीं होता है, इसलिए मुझे आश्चर्य है कि अगर मुझे समस्याओं में भाग लेने तक उन्हें वास्तव में shared_ptr का उपयोग करना चाहिए (और उन्हें एहसास है), और फिर उन्हें ठीक करें ??

आपके विचारों के लिए धन्यवाद!

भी

+0

क्या साझा किया जाएगा और पीआरआर बेहतर होगा? – DanDan

+1

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

+1

@DanDan: मुझे ऐसा नहीं लगता है, http://stackoverflow.com/questions/327573/c-passing-references-to-boostshared-ptr – Philipp

उत्तर

6

देखें हम स्पष्ट रूप से स्वामित्व को परिभाषित नहीं किया।

आपको स्पष्ट रूप से परिभाषित करने की आवश्यकता है कि कौन सा मालिक है। इसे हल करने का कोई और तरीका नहीं है। shared_ptr के कुछ उपयोगों को मनमाने ढंग से weak_ptr के साथ स्वैपिंग से चीजों को बेहतर नहीं बनाया जाएगा।

+0

ठीक है, मुझे लगता है कि यह बहुत कठिन नहीं होना चाहिए क्योंकि डिजाइन (अभी तक नहीं :-)) बहुत बुरा है, मुझे लगता है। हालांकि सवाल बनी हुई है: क्या मुझे केवल कमजोर_प्टर्स को पेश करना चाहिए जहां मुझे मंडलियों का पता लगाना चाहिए (यदि कोई और है) या हर जगह जहां ऑब्जेक्ट/विधि का स्वामित्व नहीं है? – Philipp

+1

@ फिलिप - यदि आप जो उदाहरण देते हैं उसे देखते हैं, तो कमजोर_प्टर और साझा_प्टर को पार करने के बीच व्यवहार में कोई अंतर नहीं होता है। Weak_ptr का उपयोग करने के लिए, आपको पहले से साझा_ptr बनाना होगा, जो प्रभावी रूप से पहले स्थान पर shared_ptr को पारित करने जैसा ही होता है। – Nathanael

2

कुछ लोग सही हैं: आपको पहले अपनी परियोजना में वस्तुओं के स्वामित्व के बारे में बहुत स्पष्ट तस्वीर चाहिए।

shared_ptrs साझा, यानी "समुदाय के स्वामित्व में" हैं। वह वांछनीय नहीं हो सकता है या नहीं। तो मैं स्वामित्व मॉडल को परिभाषित करने की सलाह दूंगा और उसके बाद shared_ptr semantics का दुरुपयोग न करें और सादा पॉइंटर्स का उपयोग न करें जब भी स्वामित्व को "साझा" नहीं किया जाना चाहिए।

कमजोर_प्टर का उपयोग करके इसे ठीक करने के बजाय समस्या को आगे बढ़ाया जाएगा।

4

share_ptr से weak_ptr तक ऊपर अपना डिज़ाइन बदलने में कोई फायदा नहीं है। स्वामित्व अधिकार प्राप्त करना weak_ptrs का उपयोग करने के बारे में नहीं है, यह किसी भी महत्वपूर्ण अवधि के लिए shared_ptr को संग्रहीत करने वाले प्रबंधन के बारे में है। अगर मैं किसी विधि में एक साझा_पीआरआर पास करता हूं, तो मान लीजिए कि मैं उस विधि के हिस्से के रूप में उस ऑब्जेक्ट में उस साझा_प्टर को किसी ऑब्जेक्ट में संग्रहीत नहीं करता हूं, तो मैंने उस डेटा का स्वामित्व नहीं बदला है।

मेरे अनुभव में weak_ptr का उपयोग करने का एकमात्र कारण यह है कि जब आपके पास बिल्कुल पॉइंटर्स का चक्र होना चाहिए और आपको उस चक्र को तोड़ने की आवश्यकता है। लेकिन सबसे पहले आपको इस बात पर विचार करना चाहिए कि क्या आप चक्र को खत्म करने के लिए अपने डिजाइन को संशोधित कर सकते हैं।

मैं आम तौर पर shared_ptr और कच्चे पॉइंटर्स मिश्रण को हतोत्साहित करता हूं। यह अनिवार्य रूप से होता है (हालांकि यह संभवतः नहीं होना चाहिए) कि एक कच्चे सूचक को उस फ़ंक्शन को पास करने की आवश्यकता होती है जो उस प्रकार का साझा_प्टर लेता है। एक कमजोर_प्टर को एक साझा पॉइंटर के साथ सुरक्षित रूप से एक साझा_प्टर में परिवर्तित किया जा सकता है, जिसमें आप भाग्य से बाहर हैं। इससे भी बदतर, share_ptr के अनुभवहीन अनुभवक उस कच्चे सूचक से एक नया साझा_पीआरआर बना सकते हैं और इसे फ़ंक्शन पर पास कर सकते हैं, जिससे फ़ंक्शन लौटने पर पॉइंटर को हटा दिया जा सकता है। (मुझे वास्तव में उत्पादन कोड में इस बग को ठीक करना पड़ा था, इसलिए हाँ ऐसा होता है :))

+0

"_ अनिवार्य रूप से होता है_ (...)" यह स्पष्टीकरण एसओ (या अन्यत्र) पर मैंने देखा है 'weak_ptr'' के लिए बहुत कम स्पष्ट औचित्य में से एक है। धन्यवाद। – curiousguy

3

ऐसा लगता है कि आपके पास डिज़ाइन समस्या है। shared_ptr विशिष्ट डिज़ाइन समाधान, के लिए कार्यान्वयन का उपयोग करने के लिए एक सरल प्रदान करता है लेकिन यह (न ही कुछ और) डिज़ाइन को प्रतिस्थापित कर सकता है। जब तक आप निर्धारित नहीं करते हैं कि प्रत्येक प्रकार की ऑब्जेक्ट का वास्तविक जीवनकाल क्या होना चाहिए, तो आपको shared_ptr का उपयोग नहीं करना चाहिए। एक बार जब आप कर चुके हैं, तो अधिकांश साझा_ptr/weak_ptr समस्याएं गायब होनी चाहिए।

हैं, तो यह हो रहा है, और निर्धारित किया है कि कुछ वस्तुओं के जीवनकाल अन्य वस्तुओं की है कि इस पर निर्भर करता है, और इस निर्भरता में चक्र हैं, तो आप (डिजाइन स्तर पर, फिर से) निर्धारित करने के लिए कैसे उन चक्रों का प्रबंधन करने के लिए --- यह संभव है, उदाहरण के लिए, उन मामलों में, shared_ptr सही समाधान नहीं है, या इसमें शामिल कई पॉइंटर्स केवल नेविगेशन के लिए हैं, और कच्चे पॉइंटर्स होना चाहिए।

किसी भी दर पर, आपके प्रश्न का उत्तर स्तर पर डिज़ाइन पर रहता है। अगर आपको कोडिंग के दौरान यह पूछना है, तो समय पर डिज़ाइन पर जाने का समय है।