2008-12-02 14 views
11

हमारे पास एक सी ++ लाइब्रेरी है जिसे हम कई अलग-अलग ग्राहकों को प्रदान करते हैं। हाल ही में हमने बूस्ट :: sharedptr का उपयोग करने के लिए सार्वजनिक इंटरफ़ेस में कच्चे पॉइंटर्स का उपयोग करने से स्विच किया है। इसने एक बड़ा लाभ प्रदान किया है, जैसा कि आप अनुमान लगा सकते हैं, उस समय ग्राहकों को अब चिंता करने की ज़रूरत नहीं है कि किसके लिए और कब हटाना है। जब हमने स्विच किया तो मुझे विश्वास था कि यह करना सही था, लेकिन इससे मुझे परेशान था कि हमें अपने सार्वजनिक इंटरफ़ेस में किसी तृतीय-पक्ष लाइब्रेरी से कुछ शामिल करना था - आम तौर पर यदि आप कर सकते हैं तो आप उस तरह की चीज़ से बचें। मैंने तर्कसंगत किया कि बूस्ट अब सी ++ भाषा का हिस्सा था, और हमारे उपयोग के मामले में यह आवश्यक है कि क्लाइंट कोड और लाइब्रेरी दोनों ऑब्जेक्ट्स को पॉइंटर्स रखें। हालांकि हाल ही में हमारे ग्राहकों में से एक ने हमसे पूछा है कि क्या हम इंटरफ़ेस में एक तटस्थ स्मार्ट पॉइंटर क्लास का उपयोग करने के लिए स्विच कर सकते हैं, क्योंकि हमारी लाइब्रेरी अनिवार्य रूप से उन्हें बढ़ावा देने के एक विशेष संस्करण के लिए मजबूर कर रही है- एक बिंदु जिसे मैं निश्चित रूप से समझता हूं और सराहना करता हूं। तो अब मैं सोच रहा हूं कि कार्रवाई का सबसे अच्छा तरीका क्या हो सकता है। मैंने इसके बारे में थोड़ा सोचा है, और एक साधारण स्मार्ट पॉइंटर क्लास बनाने के बारे में सोचा है जो कि वास्तविक बूस्ट स्मार्ट पॉइंटर रखता है। लेकिन फिर ग्राहक शायद उनमें से एक को बढ़ावा देने के स्वाद में साझा करेंगे :: sharedptr, और फिर हम तीन साझा पॉइंटर्स गहरे होंगे - जो एक समस्या हो सकती है, या ऐसा नहीं हो सकता है। वैसे भी, मुझे इस समस्या को हल करने के सर्वोत्तम तरीके के बारे में समुदाय से कुछ राय सुनना अच्छा लगेगा।बूस्ट का उपयोग :: लाइब्रेरी के सार्वजनिक इंटरफेस में साझा_ptr

संपादित करें: मैंने मूल रूप से स्वामित्व का हस्तांतरण कहा था, लेकिन मुझे यह निर्दिष्ट करना चाहिए था कि एपीआई सीमा के दोनों किनारों पर उस कोड को ऑब्जेक्ट को पॉइंटर रखने की आवश्यकता है।

उत्तर

13

साझा_ptr <> TR1 की रिलीज के रूप में भाषा का हिस्सा है। देखें: (TR1)

+1

हां, लेकिन हम अपने ग्राहकों को विजुअल स्टूडियो 2008 में जाने के लिए मजबूर नहीं कर सकते, जहां टीआर 1 शामिल है, आईआईआरसी। कुछ अभी भी वीएस 2005 पर हैं। –

+1

क्या आप अपने लाइब्रेरी हेडर के साथ बूस्ट TR1 फ़ोल्डर शामिल कर सकते हैं? मुझे यह देखने के लिए लाइसेंस देखना होगा कि क्या यह कानूनी है, लेकिन शायद यह है। साथ ही, चूंकि boost :: shared_ptr <> बस एक टेम्पलेट है, कोई साझा या स्थैतिक पुस्तकालय आवश्यक नहीं है। –

+2

ध्यान दें कि टीआर 1 भाषा का हिस्सा नहीं है, लेकिन यह पुस्तकालयों का एक (आधिकारिक) सूचनात्मक संग्रह है जो भविष्य के भाषा मानक का हिस्सा हो सकता है। यहां देखें: http://www.iso.org/iso/standards_development/processes_and_procedures/deliverables/iso_tr_deliverable.htm –

4

यह सी ++ है। आप जानते हैं, आप साझा सूचक कार्यान्वयन पर इंटरफ़ेस वर्ग टेम्पलेट कर सकते हैं।

+2

... जिससे आपके इंटरफेस के कार्यान्वयन को छिपाना असंभव हो जाता है क्योंकि उन्हें सभी टेम्पलेट्स की आवश्यकता होती है। स्वामित्व सॉफ्टवेयर – Bklyn

+0

@Bklyn को बेचने की कोशिश करने वाले किसी के लिए कोई अच्छा विचार नहीं है: मैं कम से कम स्ट्रिप-पैक स्रोत के बिना किसी तृतीय पक्ष C++ लाइब्रेरी का उपयोग करने की हिम्मत नहीं करता। सी ++ एबीआई बहुत नाजुक है। – Joshua

6

यदि अर्थशास्त्र वास्तव में स्वामित्व का हस्तांतरण है, तो क्यों नहीं है क्योंकि यह मानक सी ++ है auto_ptr का उपयोग करें? आंतरिक रूप से, आप अभी भी अपने share_ptr को auto_ptr से बना सकते हैं और फिर यदि आपको इसकी आवश्यकता हो तो स्वामित्व साझा किया है।

3

आप boost copy उपयोगिता को बढ़ावा देने का एक कस्टम संस्करण बनाने के लिए उपयोग कर सकते हैं जिसमें केवल स्मार्ट पॉइंटर वर्ग था। चूंकि स्मार्ट पॉइंटर क्लास हेडर-केवल लाइब्रेरी है, इसलिए इसके परिणामस्वरूप कुछ शीर्षलेख होंगे जिन्हें आप अपनी लाइब्रेरी के साथ शामिल कर सकते हैं।

18

एक संभावित समाधान आपके प्रोजेक्ट के साथ boost :: shared_ptr को शिप करना है। चूंकि इसमें सभी हेडर होते हैं, इससे आपके क्लाइंट को बूस्ट लाइब्रेरी मैन्युअल रूप से इंस्टॉल करने से मुक्त कर दिया जाएगा। आप लाइब्रेरी समेत किसी विशेष बूस्ट लाइब्रेरी द्वारा आवश्यक सभी फ़ाइलों को प्राप्त करने के लिए bcp का उपयोग कर सकते हैं। मैंने ऐसा किया जब मैंने एक कंपनी के लिए वापस काम किया और boost::shared_ptr की आवश्यकता थी और यह वास्तव में काफी काम करता था।

3

यह एक दिलचस्प सवाल है जो मैंने कुछ समय के लिए किया था। क्या आप अपने उपयोगकर्ताओं को जो भी लाइब्रेरी प्रदान करते हैं, उसमें मजबूर करते हैं, या उन्हें यह तय करने देते हैं कि उनकी परियोजना में सबसे अच्छा क्या है? हमेशा के रूप में, सवाल यह है कि आप क्या पेशकश कर रहे हैं और आपको उपयोगकर्ता से क्या आवश्यकता है।

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

अब, यदि आप स्मार्ट पॉइंटर का उपयोग करते हैं तो आप उपयोगकर्ता में अपना समाधान मजबूर कर रहे हैं। यदि वे एक स्मार्ट सूचक के अपने संस्करण का उपयोग करने की योजना बनाते हैं (कहते हैं कि आप boost :: shared_ptr का उपयोग करते हैं और वे std :: tr1 :: shared_ptr चाहते हैं) तो वे अब आपके इंटरफ़ेस के साथ काम करने के लिए इसका उपयोग करने की अनुमति नहीं देते हैं। जो भी स्मार्ट पॉइंटर आप तय करते हैं (std :: auto_ptr के अलावा यह विशेष है) आप केवल समाधान को मजबूर नहीं कर रहे हैं, बल्कि इसकी समस्याएं भी हैं।

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

एक साइड नोट के रूप में, अधिकांश स्थितियों में boost ::pt_ptr (boost 1.33+) thread safe है, और यह कई प्लेटफ़ॉर्म में लॉक-फ्री कार्यान्वयन का उपयोग करता है। वैसे भी यह आपको उन चीजों का विचार देना चाहिए जिन पर आपको विचार करना चाहिए।

अंत में, आपको यह समझना चाहिए कि आप केवल उपयोगकर्ता को अपने स्मार्ट पॉइंटर का उपयोग करने के लिए बाध्यकारी नहीं हैं, बल्कि इसका एक ही संस्करण भी उपयोग कर रहे हैं। यदि आप बूस्ट के किसी विशेष संस्करण के खिलाफ अपनी lib को संकलित करते हैं तो उपयोगकर्ता उस विशेष कार्यान्वयन से बंधे हैं

6

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

मुझे व्यक्तिगत रूप से लगता है कि आपको अपनी लाइब्रेरी के सार्वजनिक इंटरफ़ेस में बहुत अधिक फंकी सी ++ होने से बचना चाहिए क्योंकि इससे ग्राहक पर बहुत सारी समस्याएं हो सकती हैं।

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

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

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

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

एक और अच्छी विशेषता यह है कि सी ++ कार्यों के मुकाबले सी ++ कार्यों की तुलना में डीएल में कॉल करने के लिए आम तौर पर आसान है, अगर आप अपनी लाइब्रेरी को सी/सी ++ की तुलना में अन्य भाषाओं में बेनकाब करना चाहते हैं।

यह दृष्टिकोण निश्चित रूप से आपके जीवन को कई तरीकों से अधिक जटिल बनाता है, लेकिन यह कम संभावना है कि लोग आपकी लाइब्रेरी से बचें क्योंकि यह अपने कोड से सफलतापूर्वक लिंक करना संभव नहीं था।

1

बढ़ावा देने से परिचय :: shared_ptr आपके क्लाइंट को बढ़ावा देने के लिए मजबूर करता है। कुछ लोगों के लिए, यह एक मामूली मुद्दा है।

यह आपके क्लाइंट को आपके lib द्वारा उपयोग किए जाने वाले समान कंपाइलर का उपयोग करने के लिए भी मजबूर करता है, यदि आपका lib संकलित बाइनरी के रूप में वितरित किया जाता है। या, यदि आपकी लाइब्रेरी को स्रोत कोड में वितरित किया गया है, तो ग्राहकों को आपके lib को संकलित करने के लिए उपयोग किए गए कंपाइलर की अपनी पसंद से चिपके रहना होगा। यह काफी आकार की किसी भी परियोजना के लिए मामूली मुद्दा नहीं है।

1

auto_ptr का उपयोग करें या एक सी इंटरफ़ेस तक चिपके रहें। अपने इंटरफ़ेस में सी ++ libs को मजबूर करना हमेशा बदसूरत होता है, क्रॉस प्लेटफॉर्म होने का कोई मौका मारता है, और अलग-अलग "डाउनस्ट्रीम" कॉन्फ़िगरेशन वाले ग्राहकों के लिए रखरखाव दुःस्वप्न का कारण बनता है।

जैसे ही सी ++ 0x आपके ग्राहकों के लिए मुख्यधारा है, std::shared_ptr पर स्विच करें।