हेडर-ओनली लाइब्रेरीज़ के लाभ


98

हेडर के केवल लाइब्रेरी के क्या लाभ हैं और आप इसे इस तरह क्यों लिखेंगे कि कार्यान्वयन को अलग फ़ाइल में डालने का विरोध करें?


ज्यादातर टेम्प्लेट, लेकिन यह भी वितरित करना और उपयोग करना थोड़ा आसान बना देगा।
BoBTFish

4
मैं एक हेडर-ओनली लाइब्रेरी के
डाउनसाइड

ऐसे कौन से डाउनसाइड हैं जिनका पहले से उल्लेख नहीं किया गया है?
नेबुला फॉक्स

7
@mooeeeeeep: डाउनसाइड्स के लिए, आप C ++ डॉस और डोनट्स क्रोमियम प्रोजेक्ट्स वेब पेज में "स्टॉप इनलाइनिंग कोड" पैरा पढ़ना चाह सकते हैं ।
Mr.C64

जवाबों:


57

ऐसी स्थितियाँ होती हैं जब हेडर-ओनली लाइब्रेरी एकमात्र विकल्प होता है, उदाहरण के लिए जब टेम्प्लेट से निपटते हैं।

हेडर-ओनली लाइब्रेरी होने का मतलब यह भी है कि आपको उन विभिन्न प्लेटफार्मों के बारे में चिंता करने की ज़रूरत नहीं है जहाँ लाइब्रेरी का उपयोग किया जा सकता है। जब आप कार्यान्वयन को अलग करते हैं, तो आप आमतौर पर कार्यान्वयन विवरण छिपाने के लिए करते हैं, और लाइब्रेरी को हेडर और लाइब्रेरीज़ ( lib, dll's या .soफ़ाइलों) के संयोजन के रूप में वितरित करते हैं । बेशक ये सभी विभिन्न ऑपरेटिंग सिस्टम / संस्करणों के लिए संकलित किए जाने हैं जिन्हें आप समर्थन प्रदान करते हैं।

आप कार्यान्वयन फ़ाइलों को भी वितरित कर सकते हैं, लेकिन इसका मतलब है कि उपयोगकर्ता के लिए एक अतिरिक्त कदम होगा - इसका उपयोग करने से पहले अपनी लाइब्रेरी को संकलित करना।

बेशक, यह मामला-दर-मामला आधार पर लागू होता है । उदाहरण के लिए, हेडर-ओनली लाइब्रेरी कभी-कभी बढ़ जाती हैकोड का आकार और संकलन समय।


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

1
मैंने केवल हेडर के प्रदर्शन लाभ के बारे में इसी तरह का प्रश्न पूछा था। जैसा कि आप देख सकते हैं, कोड आकार में कोई अंतर नहीं है। हालांकि, उदाहरण हेडर-ओनली इम्प्लीमेंटेशन 7% धीमा चला। stackoverflow.com/questions/12290639/…
होमर 6

@ होमर 6 मुझे पिंग करने के लिए धन्यवाद। मैंने वास्तव में इसे कभी नहीं मापा है।
लुचियन ग्रिगोर

1
@ LuchianGrigore मैं किसी और को नहीं पा सकता था जो या तो था। इसलिए जवाब देने में थोड़ा समय लगा। बहुत सारे सट्टा "कोड आकार में वृद्धि" और "मेमोरी खपत" टिप्पणियां हैं। अंत में मेरे पास अंतर का एक स्नैपशॉट है, भले ही यह केवल एक उदाहरण हो।
होमर ६

@ Homer6। यह कोड आकार क्यों नहीं बढ़ाएगा? मान लें कि आप कई लिबास बनाते हैं जो हेडर का उपयोग केवल लिबास में करते हैं और फिर आपका ऐप उन सभी लिबासों का उपयोग करता है जिनके पास एक ही साझा लाइब्रेरी के खिलाफ लिंक करने के लिए कई प्रतियों के रूप में आपके पास होगा।
पोइया 13

60

हेडर-ओनली लाइब्रेरी के लाभ:

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

हेडर-ओनली लाइब्रेरी का नुकसान:

  • बड़ी वस्तु फ़ाइलें। लाइब्रेरी से प्रत्येक इनलाइन विधि जो किसी स्रोत फ़ाइल में उपयोग की जाती है, उस स्रोत फ़ाइल के लिए संकलित ऑब्जेक्ट फ़ाइल में एक कमजोर प्रतीक, आउट-ऑफ-लाइन परिभाषा प्राप्त करेगी। यह संकलक को धीमा कर देता है और लिंकर को भी धीमा कर देता है। कंपाइलर को वह सभी ब्लोट उत्पन्न करना होता है, और फिर लिंकर को इसे फ़िल्टर करना होता है।

  • लंबे समय तक संकलन। ऊपर उल्लिखित ब्लोट समस्या के अतिरिक्त, संकलन में अधिक समय लगेगा क्योंकि हेडर्स संकलित लाइब्रेरी की तुलना में हेडर-ओनली लाइब्रेरी के साथ स्वाभाविक रूप से बड़े हैं। उन बड़े हेडर को लाइब्रेरी का उपयोग करने वाली प्रत्येक स्रोत फ़ाइल के लिए पार्स करने की आवश्यकता होती है। एक और पहलू यह है कि हेडर-ओनली लाइब्रेरी में उन हेडर फाइल #includeको इनलाइन परिभाषाओं के साथ हेडर की जरूरत होती है और साथ ही हेडर की जरूरत होती है जो लाइब्रेरी को संकलित लाइब्रेरी के रूप में बनाया गया है।

  • अधिक पेचीदा संकलन। हेडर-ओनली लाइब्रेरी के साथ आपको बहुत अधिक निर्भरता मिलती है क्योंकि हेडर-ओनली लाइब्रेरी के साथ उन अतिरिक्त #includeएस की जरूरत होती है। लाइब्रेरी में कुछ प्रमुख फ़ंक्शन के कार्यान्वयन को बदलें और आपको पूरी परियोजना को फिर से तैयार करने की आवश्यकता हो सकती है। संकलित पुस्तकालय के लिए स्रोत फ़ाइल में वह परिवर्तन करें और आपको बस इतना करना है कि एक पुस्तकालय स्रोत फ़ाइल, उस नई .o फ़ाइल के साथ संकलित पुस्तकालय को अपडेट करें, और एप्लिकेशन को रिलेक्स करें।

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


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

6
@ थोमस - यहां तक ​​कि बहुत से पेशेवर पुस्तकालयों के साथ, मैं अक्सर खुद को "ठीक" हेडर पढ़ने का सहारा लेता हूं। वास्तव में, यदि तथाकथित "ठीक" प्रलेखन कोड प्लस कमेंट्री से निकाला जाता है, तो मैं आमतौर पर हेडर पढ़ना पसंद करता हूं। कोड प्लस टिप्पणियां मुझे बताती हैं कि ऑटो-जनरेट किए गए दस्तावेज़ से अधिक है।
डेविड हैमेन

2
अंतिम बिंदु मान्य नहीं है। निजी सदस्यों में हेडर पहले से ही कार्यान्वयन विवरणों से भरे होते हैं, इसलिए ऐसा नहीं है कि cpp फ़ाइल सभी कार्यान्वयन विवरणों को छिपा देती है। इसके अलावा, C # जैसी भाषाएं डिज़ाइन द्वारा अनिवार्य रूप से "हेडर केवल" हैं, और IDE अस्पष्ट विवरणों का ध्यान रखता है ("उन्हें नीचे" मोड़ना)
मार्क लाकाटा

2
@ टॉमास: सहमत, अंतिम बिंदु पूरी तरह से फर्जी है। आप आसानी से इंटरफ़ेस और कार्यान्वयन को हेडर-ओनली लाइब्रेरी के साथ अलग रख सकते हैं; आप बस इंटरफ़ेस हेडर # कार्यान्वयन विवरणों को हटा दें। यही कारण है कि बूस्ट पुस्तकालयों में आम तौर पर एक उपनिर्देशिका (और नामस्थान) शामिल होती हैं detail
निमो

4
@ थोमस: मैं असहमत हूं। हेडर फ़ाइल आम तौर पर प्रलेखन के लिए जाने वाली पहली जगह है। यदि हेडर अच्छी तरह से लिखा गया है, तो अक्सर बाहरी प्रलेखन की आवश्यकता नहीं होती है।
जोएल कॉर्नेट

14

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

यह मूल रूप से आप की अवधारणा पर आधारित है या तो लोगों को वितरित करने के लिए एक हेडर के साथ एक पुस्तकालय लिख रहा है या अपने आप को पुन: उपयोग कर रहा है बनाम हेडर में सब कुछ है। यदि आप एक हेडर और सोर्स फाइल्स को पुनः प्रयोग करने और हर प्रोजेक्ट में इनका पुनः उपयोग करने की सोच रहे हैं तो यह वास्तव में लागू नहीं होता है।

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

उदाहरण के लिए संकलक विक्रेता अक्सर संस्करणों के बीच एसटीएल के अपने कार्यान्वयन को बदलते हैं। यदि आपके पास लाइब्रेरी में कोई फ़ंक्शन है जो एक std :: वेक्टर को स्वीकार करता है, तो यह उम्मीद करता है कि उस कक्षा में बाइट्स को उसी तरह व्यवस्थित किया जाए जब वे लाइब्रेरी संकलित किए गए थे। यदि, एक नए संकलक संस्करण में, विक्रेता ने std :: वेक्टर के लिए दक्षता में सुधार किया है, तो उपयोगकर्ता का कोड नई कक्षा को देखता है जिसमें एक अलग संरचना हो सकती है और उस नई संरचना को आपके पुस्तकालय में पास कर सकती है। सब कुछ वहाँ से नीचे चला जाता है ... यही कारण है कि पुस्तकालय की सीमाओं के पार एसटीएल वस्तुओं को पारित नहीं करने की सिफारिश की जाती है। यही बात C रन-टाइम (CRT) प्रकारों पर लागू होती है।

सीआरटी के बारे में बात करते समय, आपके पुस्तकालय और उपयोगकर्ता के स्रोत कोड को आम तौर पर उसी सीआरटी के खिलाफ जोड़ा जाना चाहिए। Visual Studio के साथ यदि आप Multithreaded CRT का उपयोग करके अपनी लाइब्रेरी का निर्माण करते हैं, लेकिन उपयोगकर्ता Multithreaded Debug CRT के विरुद्ध लिंक करता है, तो आपको लिंक समस्याएँ होंगी क्योंकि आपकी लाइब्रेरी को वे प्रतीक नहीं मिल सकते हैं जिनकी उसे आवश्यकता है। मुझे याद नहीं है कि यह कौन सा समारोह था, लेकिन विजुअल स्टूडियो 2015 के लिए माइक्रोसॉफ्ट ने एक सीआरटी फ़ंक्शन इनलाइन बनाया। अचानक यह हेडर में था न कि CRT लाइब्रेरी इसलिए लाइब्रेरीज़ जो कि लिंक टाइम पर इसे ढूंढने की उम्मीद करती थीं, अब ऐसा नहीं कर सकती हैं और इस तरह की गलतियाँ हो सकती हैं। नतीजा यह हुआ कि इन पुस्तकालयों को विजुअल स्टूडियो 2015 के साथ पुन: निर्माण की आवश्यकता थी।

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

ये चीजें अन्य तृतीय पक्ष पुस्तकालयों (जैसे एक ईगन वेक्टर या जीएसएल मैट्रिक्स) से पुस्तकालय की सीमाओं के पार वस्तुओं / प्रकारों को पारित करने के लिए भी सही हैं। यदि तृतीय पक्ष पुस्तकालय आपके पुस्तकालय को संकलित करने के बीच आपके हेडर को बदल देता है और आपका उपयोगकर्ता उनके कोड को संकलित करता है तो चीजें टूट जाएंगी।

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

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

हालांकि ऐसे नकारात्मक हैं जो ऊपर उल्लेख किए गए हैं, जैसे कि संकलन का समय। इसके अलावा, आप एक व्यवसाय चला रहे हैं ताकि आप अपने सभी उपयोगकर्ताओं को चोरी करने के मामले में अपने सभी स्रोत कोड कार्यान्वयन विवरण अपने सभी उपयोगकर्ताओं को सौंपना न चाहें।


8

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


0

लिंक टाइम ऑप्टिमाइजेशन (LTO) द्वारा इनलाइनिंग की जा सकती है

मैं इसे हाइलाइट करना चाहता हूं क्योंकि यह हेडर के दो मुख्य लाभों में से केवल एक पुस्तकालयों के मूल्य को कम करता है: "आपको इनलाइन पर हेडर की परिभाषाएं चाहिए"।

इसका एक न्यूनतम ठोस उदाहरण यहां दिखाया गया है: लिंक-टाइम ऑप्टिमाइज़ेशन और इनलाइन

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

LTO का अपना डाउनसाइड भी हो सकता है: क्या कोई कारण है कि लिंक-टाइम ऑप्टिमाइज़ेशन (LTO) का उपयोग नहीं किया जाता है?

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.