Std :: string के सामने बहुत सारे स्ट्रिंग क्लास क्यों हैं?


56

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

तो, क्या कोई विशेष मिसफिट या कुछ गलत है std::string(जैसे auto_ptrशब्दार्थ खराब थे)? क्या यह C ++ 11 में बदल गया है?


32
इसे "Not Invented Here syndrome" कहा जाता है।
कैट प्लस

10
@CatPlusPlus QString और CString दोनों पूर्ववर्ती std :: string।
रोबोट

8
@ कैट प्लस प्लस: यह सिंड्रोम जावा स्ट्रिंग क्लास को प्रभावित नहीं करता है।
जियोर्जियो

20
@ जिओर्जियो: जावा प्रोग्रामर स्ट्रिंग कक्षाओं के बारे में चिंता करने के लिए भाषा की कमियों के लिए वर्कअराउंड्स का आविष्कार करने में बहुत व्यस्त हैं (Android पुनर्निर्मित स्ट्रिंग, वैसे)।
कैट प्लस प्लस

9
@ जियोर्जियो: ऐसा शायद इसलिए है क्योंकि java.lang.String(ऑपरेटर की ओवरलोडिंग, आदि की कमी) के लिए जावा का हार्ड-कोडेड सिनेटिक सपोर्ट इसे किसी और चीज का इस्तेमाल करने के लिए एक दर्द बना देगा।
मेकैनिकल घोंघा

जवाबों:


57

std::stringमानकीकृत होने से पहले उन बड़े C ++ पुस्तकालयों में से अधिकांश शुरू हो गए थे । अन्य में अतिरिक्त सुविधाएँ शामिल हैं जिन्हें देर से मानकीकृत किया गया था, या फिर भी मानकीकृत नहीं किया गया था, जैसे UTF-8 के लिए समर्थन और एन्कोडिंग के बीच रूपांतरण।

यदि उन पुस्तकालयों को आज लागू किया गया था, तो वे संभवतः ऐसे कार्यों और पुनरावृत्तियों को लिखना पसंद करेंगे जो std::stringउदाहरणों पर काम करते हैं ।


5
C ++ 98 के बाद से UTF-8 का समर्थन मानकीकृत है। इस तरह के एक असुविधाजनक और आंशिक रूप से क्रियान्वित तरीके से परिभाषित किया गया है कि कोई भी इसका उपयोग करने में सक्षम नहीं लगता है
एपीग्रामग्राम

9
@APgramgram: charकिसी भी UTF-8 कोडपॉइंट को धारण करने के लिए काफी बड़ा होने की गारंटी है। AFAIK, यह एकमात्र "समर्थन" है जो C ++ 98 प्रदान करता है।
बेन वोइग्ट

4
@ ऐपग्राम: यह समर्थन वास्तव में काफी बेकार है।
डेडएमजी

4
@AProgrammer उस स्थान को यकीनन तोड़ दिया गया wchar_tहै क्योंकि सभी यूनिकोड कोड बिंदुओं का प्रतिनिधित्व करने के लिए पर्याप्त नहीं है । इसके अलावा, यूटीएफ -16 के बारे में यह पूरी चर्चा हानिकारक थी, जहां हानिकारक माना जाता था कि बहुत ही आकर्षक तर्क दिया गया था कि यूटीएफ -8 का विशेष रूप से उपयोग किया जाना चाहिए ...
कोनराड रूडोल्फ

6
@KonradRudolph, यह स्थानीय प्रणाली नहीं है जो वहां टूटी हुई है (wchar_t की परिभाषा "किसी भी समर्थित वर्ण सेट के लिए पर्याप्त व्यापक है"); 16 बिट्स के लिए प्रतिबद्ध सिस्टम wchar_t ने एक ही समय में यूनिकोड का समर्थन नहीं करने के लिए प्रतिबद्ध किया। ठीक है, अपराधी यूनिकोड है जिसने पहले गारंटी दी थी कि यह कभी भी 16 बिट्स से अधिक की आवश्यकता वाले कोडपॉइंट्स का उपयोग नहीं करेगा, फिर सिस्टम 16 बिट्स wchar_t के लिए कमिट करता है, फिर यूनिकोड स्विचिंग को 16 बिट्स की आवश्यकता होती है।
एपीग्रामग्राम

39

स्ट्रिंग C ++ की बड़ी शर्मिंदगी है।

पहले 15 साल के लिए आप एक स्ट्रिंग कक्षा प्रदान नहीं करते हैं - प्रत्येक कंपाइलर को हर प्लेटफ़ॉर्म पर और प्रत्येक उपयोगकर्ता को स्वयं बनाने के लिए मजबूर करना।

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

जहां एक स्पष्ट स्ट्रिंग ऑपरेशन जैसे कि रिप्लेसमेंट () या मिड () में पुनरावृत्तियों की ऐसी गड़बड़ी शामिल है कि आपको एक पेज पर स्टेटमेंट फिटिंग रखने के लिए एक नया 'ऑटो' कीवर्ड शुरू करने की आवश्यकता है और अधिकांश लोगों को पूरी भाषा को छोड़ देने की ओर ले जाता है ।

और फिर आपके पास यूनिकोड 'समर्थन' और std :: wstring जो कि सिर्फ arghh है .....

<rant off> धन्यवाद - मुझे अब बहुत अच्छा लग रहा है।


12
@DeadMG - हाँ और इसे 1998 में मानकीकृत किया गया था, 15 साल के बाद इसका आविष्कार किया गया था और 6 साल बाद भी MSFT इसका उपयोग कर रहा था। हाँ पुनरावृत्तियों एक सरणी और सूची समान दिखने का एक उपयोगी तरीका है, क्या आपको लगता है कि वे स्ट्रिंग हेरफेर करने का एक स्पष्ट तरीका हैं?
मार्टिन बेकेट

3
C के साथ 1983 में आविष्कार किया गया था। न C ++। केवल मानक पुस्तकालय मानक द्वारा निर्धारित किए जाते हैं- जो, विचित्र रूप से पर्याप्त है, केवल एक बार आपके पास मानक हो सकता है, इसलिए किसी भी मानक पुस्तकालय के लिए जल्द से जल्द संभव तारीख 1998 है। और पुनरावृत्तियों को अनुक्रमित के बराबर माना जा सकता है, लेकिन दृढ़ता से टाइप किया गया। मैं सभी इस तथ्य के लिए हूं कि पुनरावृत्तियां पर्वतमाला की तुलना में चूसना करती हैं, लेकिन यह वास्तव में विशिष्ट नहीं है std::string। 1983 में एक स्ट्रिंग क्लास की कमी अब उनमें से अधिक होने का औचित्य नहीं है।
डेडएमजी

8
मैंने सोचा था कि iostreams C ++ की बड़ी शर्मिंदगी थी ...
डग टी।

18
@DeadMG लोग 1998 से पहले कई वर्षों से "C ++" नामक कुछ का उपयोग कर रहे थे। मैंने 1985 में "C ++" नामक कुछ का उपयोग करके अपना पहला कार्यक्रम लिखा था। यदि आप यह कहना चाहते हैं कि यह "वास्तविक" C ++ नहीं है, तो यह ठीक है, लेकिन इससे पहले, हम कोड लिख रहे थे और कहीं से एक स्ट्रिंग कक्षा प्राप्त करना था। एक बार जब हमारे पास इन विरासत कोडबेस होते हैं, तो जब हम एक मानक प्राप्त करते हैं, तो हम वास्तव में उन्हें बाहर नहीं फेंक सकते हैं या खरोंच से नहीं लिख सकते हैं। अब जो होना चाहिए था, वह यह था कि एक स्ट्रिंग क्लास होनी चाहिए थी जो कि cfront के साथ आई थी।
रोबोट

8
@DeadMG - अगर किसी ने ISO सर्टिफिकेट तक किसी भाषा का इस्तेमाल नहीं किया है तो कोई भी भाषा कभी भी इस्तेमाल नहीं की जाएगी क्योंकि यह कभी भी ISO को नहीं मिलेगी। X86 असेंबलर के लिए कोई आईएसओ मानक नहीं है, लेकिन मैं
मार्टिन बेकेट

32

वास्तव में ... के साथ कई मुद्दे हैं std::string, और हां यह C ++ 11 में थोड़ा बेहतर है, लेकिन चलो खुद से आगे नहीं बढ़ें।

QStringऔर पुराने पुस्तकालयों CStringका हिस्सा हैं , इसलिए वे C ++ से पहले मानकीकृत (SGI STL की तरह) अस्तित्व में थे। इस प्रकार उन्हें एक वर्ग बनाना पड़ा

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

अन्य चिंताएँ जो यहाँ विकसित नहीं हुईं (एन व्रक):

  • C ++ 03 में यह अनिवार्य नहीं है कि स्टोरेज संक्रामक हो, जिससे C संभावित रूप से मुश्किल हो जाए। C ++ 11 इसे ठीक करता है।
  • std::string अनजान है, और UTF-8 के लिए कोई विशेष कोड नहीं है, इसमें UTF-8 स्ट्रिंग संग्रहीत करना और इसे अनजाने में भ्रष्ट करना आसान है
  • std::stringइंटरफ़ेस फूला हुआ है , कई तरीकों को फ्री-फ़ंक्शंस के रूप में लागू किया जा सकता था और कई को इंडेक्स-आधारित इंटरफ़ेस और एक इटेरेटर-आधारित इंटरफ़ेस दोनों के अनुरूप बनाने के लिए डुप्लिकेट किया गया है।

5
फिर से चिंता करें # 1 - C ++ 03 21.3.6 / 1 गारंटी देता है कि c_str()एक सूचक को सन्निहित भंडारण में लौटाता है, जो कुछ सी-इंटरऑपरेबिलिटी प्रदान करता है। हालाँकि आप इंगित किए गए डेटा को संशोधित नहीं कर सकते। विशिष्ट वर्कअराउंड में a का उपयोग करना शामिल है vector<char>
जॉन डिब्लिंग

@ जॉनडब्लिंग: हाँ, और एक और सीमा है: यह नए आवंटित भंडारण में एक प्रति खरीद सकता है (मानक यह नहीं कहता कि यह नहीं होगा)। बेशक C ++ 11 या तो नकल करने से नहीं रोकता है, लेकिन जब से आप बस कर सकते हैं &s[0]तो इससे कोई फर्क नहीं पड़ता :)
Matthieu M.

1
@ मैथ्यूएमएम .: पॉइंटर के माध्यम से प्राप्त &s[0]एनयूएल-टर्मिनेटेड स्ट्रिंग (जब तक c_str()कि अंतिम संशोधन के बाद से कॉल नहीं किया गया है) को इंगित नहीं किया जा सकता है ।
बेन वोइगट

2
@ मैथ्यू: एक और बफर की अनुमति नहीं है। " c_str()रिटर्न: एक पॉइंटर pऐसा जो p + i == &operator[](i)प्रत्येक iके लिए [0,size()]"।
बेन वोइगट

3
यह भी ध्यान देने योग्य है कि उनके सही दिमाग में कोई भी MFC का उपयोग नहीं करता है, इसलिए यह तर्क देना कठिन है कि CString आधुनिक C ++ में एक स्ट्रिंग क्लास है।
डेडएमजी

7

यहां पोस्ट किए गए कारणों के अलावा एक और एक भी है - द्विआधारी संगतता । पुस्तकालयों के लेखकों का इस बात पर कोई नियंत्रण नहीं है std::stringकि आप किस कार्यान्वयन का उपयोग कर रहे हैं और क्या उनका मेमोरी लेआउट भी उनके जैसा है।

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

यदि केवल लेआउट अलग है, तो कुछ std::stringसदस्य फ़ंक्शन लाइब्रेरी से क्लाइंट को दिए गए इंस्टेंस पर कॉल करते हैं या आसपास का अन्य तरीका विफल हो सकता है, यह निर्भर करता है कि किन सदस्यों को स्थानांतरित किया गया था।

यदि आकार अलग- std::stringअलग है, तो पुस्तकालय में और ग्राहक कोड में जांचे जाने पर सभी पुस्तकालय प्रकार के सदस्य अलग-अलग आकार के दिखाई देंगे। निम्न std::stringसदस्य के डेटा सदस्यों के पास ऑफ़सेट के रूप में अच्छी तरह से स्थानांतरित कर दिया जाएगा, और क्लाइंट से कॉल किए जाने वाले किसी भी सीधे एक्सेस / इनलाइन एक्सेसर को पुस्तकालय में डिबगिंग करते समय "ठीक लग रही है" के बावजूद बकवास वापस आ जाएगी।

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

निष्पक्ष होने के लिए, यह सभी एसटीएल प्रकारों पर लागू होता है। IIRC में उनके पास मेमोरी लेआउट नहीं है।


2
आपको एक * निक्स प्रोग्रामर होना चाहिए। C ++ बाइनरी संगतता सभी प्लेटफ़ॉर्म पर समान नहीं है, और विशेष रूप से Windows NO वर्ग पर जिसमें डेटा सदस्य कंपाइलर के बीच पोर्टेबल हैं।
बेन वोइगट

(मेरा मतलब है कि POD प्रकारों को छोड़कर, और फिर भी स्पष्ट पैकिंग आवश्यकताओं की आवश्यकता है)
Ben Voigt

1
इनपुट के लिए धन्यवाद, हालांकि मैं अलग संकलक की बात नहीं कर रहा हूं, मैं अलग एसटीएल की बात कर रहा हूं।
gwiazdorrr

1
+1: ABI एक संकलित आपूर्ति वर्ग के अपने स्वयं के संस्करण को रोल करने का एक बड़ा कारण है। उस अकेले के लिए, मैं चाहता हूं कि यह स्वीकृत उत्तर था।
थॉमस ईडिंग

6

प्रश्न के कई उत्तर हैं लेकिन यहाँ कुछ हैं:

  1. विरासत। कई स्ट्रिंग पुस्तकालयों और कक्षाओं को PRIOR को std :: string के अस्तित्व के लिए लिखा गया था।

  2. C. कोड में कोड के साथ संगतता के लिए पुस्तकालय std :: string C ++ है जहाँ पर अन्य स्ट्रिंग लाइब्रेरीज़ हैं जो C और C ++ के साथ काम करती हैं।

  3. गतिशील आवंटन से बचने के लिए। लाइब्रेरी एसटीडी :: स्ट्रिंग डायनेमिक एलोकेशन का उपयोग करती है और यह एम्बेडेड सिस्टम, इंटरप्ट या रियल-टाइम संबंधित कोड, या निम्न-स्तरीय कार्यक्षमता के लिए उपयुक्त नहीं हो सकती है।

  4. टेम्पलेट्स। लाइब्रेरी std :: string टेम्प्लेट पर आधारित है। हाल ही में जब तक सी ++ संकलकों की एक संख्या ने खराब प्रदर्शन या यहां तक ​​कि छोटी गाड़ी का समर्थन किया था। दुर्भाग्य से, मैं एक ऐसे उद्योग में काम करता हूं जो बहुत सारे कस्टम टूल का उपयोग करता है और उद्योग में एक प्रमुख खिलाड़ी से हमारे टूलचिन में से एक "आधिकारिक तौर पर" 100% समर्थन सी ++ (छोटी गाड़ी सामान टेम्पलेट एट अल के साथ) नहीं करता है।

संभवतः कई और वैध कारण भी हैं।


2
"हाल ही में" अर्थ "यह एक दशक हो गया है क्योंकि विजुअल स्टूडियो के पास उनके लिए बहुत उचित समर्थन था"?
डेडएमजी

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

4

यह ज्यादातर यूनिकोड के बारे में है। यूनिकोड के लिए मानक समर्थन सबसे अच्छा है, और हर किसी की अपनी यूनिकोड की जरूरत है। उदाहरण के लिए, ICU आपके द्वारा कभी भी सबसे अधिक घृणित स्वचालित रूप से उत्पन्न-से-जावा इंटरफ़ेस के पीछे आपके द्वारा चाहा जा सकने वाले हर यूनिकोड की कार्यक्षमता का समर्थन करता है, और यदि आप यूनिक्स पर यूटीएफ -16 के साथ अटके हुए हैं, तो आपके विचार का भला नहीं हो सकता है अच्छा समय।

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

मेरी राय में, यह ज्यादातर C ++ समिति का दोष है, जो कि यूनिकोड के लिए सही ढंग से समर्थन प्रदान नहीं करता है- 1998 या 2003 में, शायद यह समझने योग्य था, लेकिन C ++ 11 में नहीं। उम्मीद है कि C ++ 17 में वे बेहतर प्रदर्शन करेंगे।


नमस्कार, C ++ 20 यहाँ, यूनिकोड समर्थन का क्या हुआ?
राहगीर

-4

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


7
क्या यह सच है मैं जावा जैसी भाषाओं में स्ट्रिंग कार्यान्वयन की एक समान संख्या देखने की उम्मीद करूंगा जहां एक अच्छा कार्यान्वयन सभी के साथ उपलब्ध है।
बिल के

@BillK जावा स्ट्रिंग अंतिम है, इसलिए आपको नई कार्यक्षमता को कहीं और रखना होगा।

और मेरा कहना है, यहाँ तक कि अंतिम रूप से, 20 वर्षों में, मैंने कभी किसी को कस्टम स्ट्रिंग इम्पेलमेंट (राइट वेल) लिखा हुआ नहीं देखा (खैर, मैंने स्ट्रिंग कॉन्फ्रेनेशन परफॉर्मेंस को बेहतर बनाने का प्रयास किया था, लेकिन यह पता चला है कि जावा आपसे स्ट्रिंग + स्ट्रिंग में अधिक स्मार्ट है ') डी कल्पना)
बिल के

2
@ बिल: यह एक अलग संस्कृति के साथ करना पड़ सकता है। C ++ उन लोगों को आकर्षित करता है जो निम्न-स्तरीय विवरणों को समझना चाहते हैं। जावा उन लोगों को आकर्षित करता है जो सिर्फ किसी और के बिल्डिंग ब्लॉकों का उपयोग करके काम करना चाहते हैं। (ध्यान दें कि यह या तो भाषा का उपयोग करने के लिए चुनने वाले किसी विशिष्ट व्यक्ति के बारे में बयान नहीं है, लेकिन भाषाओं के संबंधित डिजाइन लक्ष्यों और संस्कृति के बारे में)
बेन वोइगट
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.