2011-03-16 8 views
8

मान लीजिए मैं:shared_ptr - संदर्भ द्वारा बनाम पास मूल्य से गुजरती

typedef boost::shared_ptr<Event> EventPtr; 

एक थ्रेड पर, मैं एक Event बनाने रहा हूँ और यह बंद भेजने भेजा करने के लिए:

Event* event = new Event(); 
EventPtr eventPtr(event); 
EventDispatcher::dispatch(eventPtr); //pseudocode 

EventDispatcher प्राप्त करता है एक EventPtr और इसे एक कतार में जोड़ता है जो किसी अन्य थ्रेड में संसाधित हो जाता है ... लेकिन प्रेषण विधि के लिए उपयुक्त विधि हस्ताक्षर क्या है?

dispatch(EventPtr event); //will push_back(event) 

या

dispatch(const EventPtr& event); //will push_back(event); 

ध्यान में रखते हुए मेरी EventDispatcher एक कतार है:

typedef std::queue<EventPtr> EventQueue 
EventQueue theQueue; 

फिर बाद में, अन्य धागा कुछ कार्रवाई करने के लिए करने के लिए कतार और इसे हाथों से बंद एक घटना पॉप घटना:

EventPtr event = theQueue.front(); 
EventProcessor::process(event); //pseudocode 
theQueue.pop(); 

फिर, process विधि के लिए उचित विधि हस्ताक्षर क्या है? मैं सोच रहा हूं कि क्या मैं प्रक्रिया विधि में नग्न Event* पास कर सकता हूं?

मुझे लगता है कि मुझे आश्चर्य है कि मुझे केवल मूल्य से गुजरना है, इसलिए संदर्भ गणना सटीक है? मैं वास्तव में इस तथ्य के बारे में चिंतित हूं कि एक धागा कतार पर धक्का दे रहा है और दूसरा धागा कतार से बाहर निकल रहा है और मैं कहीं भी पॉइंटर्स को रिसाव नहीं कर रहा हूं ...

धन्यवाद!

उत्तर

4

इवेंट डिस्पैचर को इवेंटप्रेट प्राप्त होता है और इसे एक कतार में जोड़ता है जो किसी अन्य थ्रेड में संसाधित हो जाता है ... लेकिन प्रेषण विधि के लिए उपयुक्त विधि हस्ताक्षर क्या है?

या तो सुझाव ठीक है; कॉन्स संदर्भ से गुज़रने की संभावना अधिक कुशल होगी, क्योंकि इसे सूचक की संदर्भ गणना को संशोधित नहीं करना पड़ेगा। किसी भी मामले में, push_back कतार पर पॉइंटर की प्रतिलिपि रखेगा, कतार पर होने पर ईवेंट को जीवित रखेगा।

फिर, प्रक्रिया विधि के लिए उपयुक्त विधि हस्ताक्षर क्या है? मैं सोच रहा हूं कि क्या मैं सिर्फ प्रक्रिया विधि में नग्न घटना * पास कर सकता हूं?

साझा सूचक (मूल्य या संदर्भ द्वारा) पासिंग स्पष्ट रूप से दस्तावेज़ जाएगा और घटना के स्वामित्व को लागू करने, और प्रोसेसर process() करने के लिए कॉल के बाद यह की पकड़ रखने के लिए अगर यह करने की जरूरत है की अनुमति देगा। कच्चे सूचक को पास करना स्वामित्व में अनिश्चितता का परिचय देता है; प्रोसेसर को एक अनुबंध की आवश्यकता होगी जिसमें कहा गया है कि यह घटना का स्वामित्व नहीं ले रहा है, और इसे process() समाप्त होने के बाद इसे एक्सेस करने का प्रयास नहीं करना चाहिए।

1

बड़ी तस्वीर में, इससे कोई फर्क नहीं पड़ता कि आप मूल्य या संदर्भ से गुजरते हैं या नहीं। किसी भी तरह से, जब आप shared_ptr को कतार पर धक्का देने के लिए प्रतिलिपि बनाते हैं तो संदर्भ गणना बढ़ाई जाएगी।

नग्न पॉइंटर पास करना ठीक है, जब तक आप सावधान रहें, आप अलग-अलग संदर्भ संख्याओं के साथ दो अलग-अलग shared_ptr उदाहरणों के साथ समाप्त नहीं होते हैं, कॉलर में से एक और कैली में से एक।

व्यक्तिगत रूप से, मुझे पास-बाय-वैल्यू विकल्प पसंद है क्योंकि यह वास्तविक पॉइंटर को पास करने जैसा लगता है। एक तर्क के रूप में shared_ptr की आवश्यकता के लिए प्रोग्रामर को फ़ंक्शन को कॉल करने की याद दिलाती है कि यह ऑब्जेक्ट का जीवनकाल फ़ंक्शन कॉल से अधिक होना चाहता है और कॉलर shared_ptr में तर्क को संग्रहीत करना चाहेगा यदि कोई अपवाद है तो फ़ंक्शन प्रारंभ होने पर फेंक दिया, आदि

0

दोनों प्रेषण कार्य ठीक से काम करेंगे।

पहले मामले में, साझा पॉइंटर का एक उदाहरण स्टैक पर कॉपी किया जाएगा और फिर ईवेंट कतार में जोड़े जाने पर फिर से कॉपी किया जाएगा। इसका मतलब सूचक की प्रतिलिपि बनाना और संदर्भ काउंटर में वृद्धि करना है।

dispatch(EventPtr event); //will push_back(event) 

दूसरे मामले में केवल एक मौजूदा उदाहरण का संदर्भ समारोह में पास किया जाएगा और फिर कतार में कॉपी किया जाएगा। मैं इस संस्करण का उपयोग करूंगा।

dispatch(const EventPtr& event); //will push_back(event); 

जब प्रक्रिया() से साझा सूचक गुजर, आप भी यह संदर्भ द्वारा पारित कर सकते हैं:

class EventProcessor { 
    process(const EventPtr& event); 
}