क्या आजकल सी + स्ट्रिंग में सी-स्ट्रिंग का उपयोग करने का कोई अच्छा कारण है? मेरी पाठ्यपुस्तक उन्हें कुछ बिंदुओं पर उदाहरणों में उपयोग करती है, और मुझे लगता है कि यह एक std :: स्ट्रिंग का उपयोग करना आसान होगा।सी ++ में सी स्ट्रिंग का उपयोग क्यों करें?
उत्तर
सीआई स्टाइल स्ट्रिंग का उपयोग करने वाले तृतीय पक्ष पुस्तकालयों के साथ इंटरफेसिंग करते समय मुझे उनका उपयोग करने का एकमात्र कारण है। ऐसी गूढ़ परिस्थितियां भी हो सकती हैं जहां आप प्रदर्शन कारणों से सी स्टाइल स्ट्रिंग का उपयोग करेंगे, लेकिन अधिकतर नहीं, सी ++ तारों पर विधियों का उपयोग करना शायद इनलाइनिंग और विशेषज्ञता आदि के कारण तेज़ है।
आप c_str()
विधि का उपयोग कर सकते हैं कई मामलों में एपीआई के साथ काम करते समय, लेकिन आपको पता होना चाहिए कि char * लौटा हुआ है, और आपको उस पॉइंटर के माध्यम से स्ट्रिंग को संशोधित नहीं करना चाहिए। उन स्थितियों में, आप अभी भी वेक्टर <char> का उपयोग कर सकते हैं, और कम से कम आसान मेमोरी प्रबंधन का लाभ प्राप्त कर सकते हैं।
क्योंकि इस तरह वे कई एपीआई/पुस्तकालयों से आते हैं?
एसटीएल तारों का उपयोग करना निश्चित रूप से कहीं अधिक आसान है, और मुझे उनका उपयोग करने का कोई कारण नहीं दिख रहा है।
यदि आपको ऐसी लाइब्रेरी से बातचीत करने की आवश्यकता है जो केवल सी-स्टाइल स्ट्रिंग को तर्क के रूप में लेता है, तो आप स्ट्रिंग क्लास की c_str() विधि को हमेशा कॉल कर सकते हैं।
c_str() के साथ एकमात्र समस्या यह है कि जो सूचक आप वापस प्राप्त करते हैं वह है। आपको उस स्ट्रिंग के माध्यम से सामग्री को संशोधित नहीं करना चाहिए। इस तरह की स्थितियों में, आप एक वेक्टर
समझा, मैं पुस्तकालय में तारों को पारित करने और उन्हें बाहर नहीं निकालने का जिक्र कर रहा था। –
मान लें कि आपके कोड में कुछ स्ट्रिंग स्थिरांक हैं, जो एक बहुत ही सामान्य आवश्यकता है। सी ++ ऑब्जेक्ट्स की तुलना में इन्हें सी स्ट्रिंग के रूप में परिभाषित करना बेहतर है - अधिक हल्के, पोर्टेबल इत्यादि। अब, यदि आप इन कार्यों को विभिन्न कार्यों में पारित करने जा रहे हैं, तो यह अच्छा है कि ये फ़ंक्शन एक सी स्ट्रिंग को स्वीकार करने की बजाय स्वीकार करते हैं सी ++ स्ट्रिंग ऑब्जेक्ट।
बेशक, यदि स्ट्रिंग्स म्यूटेबल हैं, तो सी ++ स्ट्रिंग ऑब्जेक्ट्स का उपयोग करना अधिक सुविधाजनक है।
ध्यान दें कि एक सी ++ स्ट्रिंग ऑब्जेक्ट को स्वीकार करने वाले वही कार्य, अंतर्निहित निर्माण के कारण सी स्ट्रिंग को स्वीकार करेंगे, इसलिए, उन कार्यों को चारों ओर रखने का कोई कारण नहीं है। "अधिक हल्के" और "अधिक पोर्टेबल" के लिए, भुगतान करने की कीमत पॉइंटर्स (और उन्हें परीक्षण करने के लिए) है। मेरे लिए उच्च ... – paercebal
यह सच है कि कुछ फ़ंक्शन एक C++ स्ट्रिंग ऑब्जेक्ट स्वीकार करेंगे, लेकिन कुछ नहीं करेंगे। भी, अंतर्निहित निर्माण एक प्रदर्शन लागत है। लेकिन हाँ, ट्रेडऑफ हैं ... – adum
यदि सी ++ कोड "गहरा" है (कर्नेल के करीब, सी पुस्तकालयों पर भारी निर्भर करता है) तो आप std :: स्ट्रिंग में और बाहर के कई रूपांतरणों से बचने के लिए स्पष्ट रूप से सी स्ट्रिंग का उपयोग करना चाह सकते हैं। यदि आप अन्य भाषा डोमेन (पायथन, रूबी इत्यादि) के साथ इंटरफेसिंग कर रहे हैं, तो आप इसी कारण से ऐसा कर सकते हैं। अन्यथा, std :: स्ट्रिंग का उपयोग करें।
यदि किसी फ़ंक्शन को स्थिर स्ट्रिंग की आवश्यकता होती है तो मैं अभी भी 'const char *' (या const wchar_t *) का उपयोग करना पसंद करता हूं भले ही प्रोग्राम std :: string, CString, EString या कहीं और कहीं भी उपयोग करता हो।
एक बड़े कोड बेस में तारों के बहुत सारे स्रोत हैं यह सुनिश्चित करने के लिए कि कॉलर के पास स्ट्रिंग :: स्ट्रिंग और स्ट्रिंग के रूप में स्ट्रिंग होगी और 'कॉन्स्ट char *' सबसे कम आम denominator है।
पसंद को देखते हुए, आमतौर पर सी ++ स्ट्रिंग्स (std::string
) पर आदिम सी स्ट्रिंग्स (char*
) चुनने का कोई कारण नहीं है। हालांकि, अक्सर आपके पास पसंद की लक्जरी नहीं होती है। उदाहरण के लिए, std::fstream
के रचनाकार ऐतिहासिक कारणों से सी स्ट्रिंग लेते हैं। इसके अलावा, सी पुस्तकालयों (आपने अनुमान लगाया है!) सी तारों का उपयोग करें।
अपने स्वयं के सी ++ कोड में std::string
का उपयोग करना सबसे अच्छा है और c_str()
function of std::string
का उपयोग कर आवश्यक वस्तु के सी स्ट्रिंग को निकालने के लिए सबसे अच्छा है।
और निश्चित रूप से, आपको स्ट्रिंग अक्षर के लिए सी-स्टाइल स्ट्रिंग का उपयोग करना होगा। – dan04
@ dan04 जरूरी नहीं है। दिया गया 'शून्य एफ (std :: स्ट्रिंग एस);' आप 'f ("सी स्ट्रिंग") के साथ फ़ंक्शन को कॉल कर सकते हैं; क्योंकि एक सी स्ट्रिंग पूरी तरह से 'std :: string' में डाली जा सकती है। – wilhelmtell
पाठ्यपुस्तकों में पुराने स्कूल सी स्ट्रिंग्स की सुविधा है क्योंकि कई बुनियादी कार्य अभी भी उन्हें तर्क के रूप में उम्मीद करते हैं, या उन्हें वापस कर देते हैं। इसके अतिरिक्त, यह स्मृति में स्ट्रिंग की अंतर्निहित संरचना में कुछ अंतर्दृष्टि देता है।
यह आपके द्वारा उपयोग की जा रही पुस्तकालयों पर निर्भर करता है।उदाहरण के लिए, MFC के साथ काम करते समय, विंडोज एपीआई के विभिन्न हिस्सों के साथ काम करते समय सीएसटींग का उपयोग करना अक्सर आसान होता है। यह Win32 अनुप्रयोगों में std :: स्ट्रिंग से बेहतर प्रदर्शन करने लगता है।
हालांकि, std :: स्ट्रिंग सी ++ मानक का हिस्सा है, इसलिए यदि आप बेहतर पोर्टेबिलिटी चाहते हैं, तो std :: string के साथ जाएं।
अधिकतर एम्बेडेड प्लेटफ़ॉर्म जैसे अनुप्रयोगों के लिए जहां आपके पास तारों को छेड़छाड़ करने के लिए एक ढेर की लक्जरी नहीं है, और जहां स्ट्रिंग बफर के निर्धारक प्रीलोकेशन की आवश्यकता होती है।
क्या string.reserve() निर्धारक प्रीलोकेशन की अनुमति नहीं देता है? –
@ जेसन - ऐसा हो सकता है कि आपके पास ढेर हो। – mattnz
सी तारों में कक्षा होने का उपर नहीं है।
ग तार आम तौर पर तेजी कोड में परिणाम कर सकते हैं, क्योंकि वे मशीन के स्तर के करीब
यह नहीं कहा जा रहा है कर रहे हैं, तो आप उन लोगों के साथ बुरा कोड नहीं लिख सकते हैं। हर दूसरे निर्माण की तरह उनका दुरुपयोग किया जा सकता है।
मुक्ति कॉलों की एक संपत्ति है जो उन्हें ऐतिहासिक कारणों से मांगती है।
सी तारों, और एसटीएल तारों का उपयोग करना सीखें, और ऐसा करने के लिए समझ में आने पर प्रत्येक का उपयोग करें।
ऐसा करने का सामान्य कारण यह है कि आप अपनी स्ट्रिंग हैंडलिंग में बफर ओवरफ़्लो लिखने का आनंद लेते हैं। गिनती तारों को समाप्त तारों से बहुत बेहतर होता है यह देखना कठिन होता है कि सी डिजाइनरों ने कभी तारों को समाप्त क्यों नहीं किया। यह तब एक बुरा निर्णय था; अब यह एक बुरा फैसला है।
पास्कल स्टाइल स्ट्रिंग्स (लम्बाई पहले) और सी स्टाइल स्ट्रिंग्स (शून्य समाप्त) दोनों के साथ काम करने के बाद मुझे सी स्ट्रिंग्स के साथ कम समस्याएं आई हैं। उस ने कहा कि पास्कल शैली कुछ ओप्स के लिए अधिक कुशल हैं। – maccullt
@DrPizza - मैंने आपको वोट नहीं दिया, लेकिन जब मैंने आपकी पोस्ट देखी, तो मुझे पता था कि यह -1 क्यों था ... व्यक्तिगत रूप से, मुझे लगता है कि यह आपके उत्तर पर एक शब्द था। लेकिन, मैं आपकी टिप्पणियों से भी सहमत हूं। कभी-कभी जानना अच्छा होगा कि किसी ने वोट देने का फैसला क्यों किया। शायद भविष्य के उपयोग के लिए एक सुझाव? – LarryF
-1 क्योंकि आप अपनी राय पेश कर रहे हैं जैसे कि यह तथ्य था। –
मेमोरी नियंत्रण। मुझे हाल ही में बड़े पैमाने पर बहुप्रचारित अनुप्रयोग में 200-300 एमबी आकार में स्ट्रिंग्स (वास्तव में डेटाबेस से ब्लब्स) को संभालना पड़ा था। यह एक ऐसी स्थिति थी जहां स्ट्रिंग की एक और प्रतिलिपि ने 32 बिट एड्रेस स्पेस को फटकारा होगा। मुझे पता होना था कि स्ट्रिंग की कितनी प्रतियां मौजूद थीं। हालांकि मैं एक एसटीएल प्रचारक हूं, फिर भी मैंने char * का उपयोग किया क्योंकि उसने मुझे गारंटी दी कि कोई अतिरिक्त मेमोरी या अतिरिक्त प्रति आवंटित नहीं की गई थी। मुझे पता था कि वास्तव में कितनी जगह की आवश्यकता होगी।
इसके अलावा, मानक एसटीएल स्ट्रिंग प्रोसेसिंग स्ट्रिंग प्रोसेसिंग/पार्सिंग के लिए कुछ महान सी कार्यों पर चूक जाती है। शुक्र है, std :: स्ट्रिंग में आंतरिक बफर तक पहुंच के लिए c_str() विधि है। Printf() का उपयोग करने के लिए आपको अभी भी char * का उपयोग करना होगा (हालांकि सी ++ टीम का एक पागल विचार है जिसमें प्रिंटफ-जैसी कार्यक्षमता शामिल नहीं है, सी में सबसे उपयोगी कार्यों में से एक है। मुझे आशा है कि बूस्ट :: प्रारूप होगा जल्द ही एसटीएल में शामिल किया जाना
sprintf- जैसी कार्यक्षमता वहां है - आपको बस एक स्ट्रिंग स्ट्रीम और मानक आउटपुट ऑपरेटरों का उपयोग करने की आवश्यकता है। – Branan
@ ब्रानन: हाँ, लेकिन यह वही बात नहीं है और यदि आपको बहुत से पैरामीटर की आवश्यकता है तो यह बहुत तेज हो जाता है ... –
एक जोड़े को और अधिक स्मृति नियंत्रण नोट:।।
सी तार पॉड प्रकार के होते हैं, तो वे अपने आवेदन की केवल पढ़ने के लिए डेटा सेगमेंट में आवंटित किया जा सकता है यदि आप यह घोषणा करते हैं और कम से std::string
स्थिरांक को परिभाषित नेमस्पेस स्कोप, कंपाइलर अतिरिक्त कोड उत्पन्न करेगा जो main()
से पहले चलता है जो प्रत्येक स्थिर के लिए std::string
कन्स्ट्रक्टर को कॉल करता है। यदि आपके एप्लिकेशन में कई स्थिर स्ट्रिंग हैं (उदाहरण के लिए यदि आपने सी ++ कोड जेनरेट किया है जो निरंतर तारों का उपयोग करता है), सी स्ट्रिंग्स वें में बेहतर हो सकती हैं स्थिति है
std::string
के कुछ कार्यान्वयन एसएसओ ("शॉर्ट स्ट्रिंग ऑप्टिमाइज़ेशन" या "छोटे स्ट्रिंग ऑप्टिमाइज़ेशन") नामक एक सुविधा का समर्थन करते हैं, जहां std::string
कक्षा में एक निश्चित लंबाई तक तारों के लिए भंडारण होता है। यह std::string
का आकार बढ़ाता है लेकिन अक्सर प्रदर्शन में सुधार, मुक्त स्टोर आवंटन/विध्वंस की आवृत्ति को कम करता है। यदि std::string
का कार्यान्वयन एसएसओ का समर्थन नहीं करता है, तो स्टैक पर खाली std::string
का निर्माण करना अभी भी एक फ्री-स्टोर आवंटन करेगा। यदि ऐसा है, तो अस्थायी स्टैक-आवंटित सी स्ट्रिंग का उपयोग प्रदर्शन-महत्वपूर्ण कोड के लिए सहायक हो सकता है जो तारों का उपयोग करता है।बेशक, आपको सावधान रहना होगा कि जब आप ऐसा करते हैं तो पैर में खुद को शूट न करें।
कुछ पोस्ट मेमोरी चिंताओं का उल्लेख करते हैं। यह std :: स्ट्रिंग को छोड़ने का एक अच्छा कारण हो सकता है, लेकिन char * शायद सबसे अच्छा प्रतिस्थापन नहीं है। यह अभी भी एक ओओ भाषा है। आपकी खुद की स्ट्रिंग क्लास शायद char * से बेहतर है। यह और भी अधिक कुशल हो सकता है - उदाहरण के लिए, आप छोटे स्ट्रिंग अनुकूलन को लागू कर सकते हैं।
मेरे मामले में, मैं 2 जीबी फ़ाइल से लगभग 1 जीबी लायक स्ट्रिंग प्राप्त करने की कोशिश कर रहा था, उन्हें 60 फ़ील्ड के साथ रिकॉर्ड में रखता था और फिर उन्हें विभिन्न क्षेत्रों के 7 गुना क्रमबद्ध करता था। मेरे पूर्ववर्ती कोड को char * के साथ 25 घंटे लग गए, मेरा कोड 1 घंटे में चला।
1) "स्ट्रिंग स्थिर" एक सी स्ट्रिंग (कॉन्स char *) है, इसे std :: string & में कनवर्ट करना रन-टाइम प्रक्रिया है, जरूरी नहीं कि सरल या अनुकूलित हो। 2) fstream लाइब्रेरी फ़ाइल नाम पास करने के लिए सी-स्टाइल स्ट्रिंग का उपयोग करती है।
अंगूठे का मेरा नियम कॉन्स std :: स्ट्रिंग & पास करना है यदि मैं डेटा को std :: स्ट्रिंग के रूप में उपयोग करने वाला हूं (कहें, जब मैं उन्हें वेक्टर में संग्रहीत करता हूं), और अन्य मामलों में char * ।
दूर-दूर तक खर्च करने के बाद, शुरुआती नियमों को डीबग करने और कई प्लेटफार्मों पर हर कल्पनीय स्ट्रिंग कार्यान्वयन के लिए हमें स्थैतिक तारों को स्थिरांक की आवश्यकता होती है *।
खराब चार्ट * कोड और मेमोरी लीक को डिबग करने में बहुत अधिक समय व्यतीत करने के बाद, मैं सुझाव देता हूं कि सभी गैर स्थैतिक तार कुछ प्रकार की स्ट्रिंग ऑब्जेक्ट हों ... जब तक प्रोफाइलिंग दिखाता है कि आप कुछ बेहतर कर सकते हैं और करना चाहिए; -)
विरासत कोड जो std :: string के बारे में नहीं जानता है। इसके अलावा, सीडी + 11 ओपनिंग फाइलों से पहले std :: ifstream या std :: ofstream फ़ाइल नाम में इनपुट के रूप में केवल कॉन्स्ट char * के साथ संभव था।
वापसी मूल्य एक कारण के लिए आधार है। एक const_cast या सी कास्ट का उपयोग करके इसे संशोधित करना आंतरिक ऑब्जेक्ट स्थिति को सिंक्रनाइज़ करना है। इसे 'संशोधित नहीं करना चाहिए' पढ़ना चाहिए, न कि 'नहीं होना चाहिए'। – Thorsten79