2012-04-05 13 views
12

"किसी को हमेशा सी-स्टाइल स्ट्रिंग्स (char *) पर std::string का उपयोग करना चाहिए" सलाह है जो यहां पोस्ट किए गए लगभग हर स्रोत कोड के लिए आता है। हालांकि सलाह में कोई संदेह नहीं है, वास्तविक प्रश्नों को संबोधित किए जाने पर पर विस्तार करने की अनुमति क्यों नहीं है? विस्तार से सलाह के पहलू। यह सवाल इसके लिए प्लेसहोल्डर के रूप में कार्य करना है।सी ++ में सी-स्टाइल स्ट्रिंग पर किसी को std :: स्ट्रिंग का उपयोग क्यों करना चाहिए?

एक अच्छा जवाब निम्नलिखित पहलुओं (विस्तार से) को शामिल करना चाहिए:

  1. एक std::string सी ++ में सी शैली तार के ऊपर क्यों इस्तेमाल करना चाहिए?
  2. #1 में उल्लिखित अभ्यास के नुकसान (यदि कोई हैं) क्या हैं?
  3. #1 में उल्लिखित सलाह के विपरीत परिदृश्य क्या हैं?
+0

मैं इस [सी ++ - फैक] (http://stackoverflow.com/questions/tagged/c%2b%2b-faq) को टैग करने की योजना बना रहा हूं और [सी ++ लाउंज] (http: // चैट में इसकी चर्चा करूंगा) जल्द ही .stackoverflow.com/कमरे/10/लाउंजक)। –

+2

यह अभी भी 2012 में पूछा जा रहा है ?! साथ ही, 'std :: string' का उपयोग करने की सलाह कब ** ** ** तर्कसंगतता के साथ नहीं है? –

+1

@ karlKnechtel: क्षमा करें, लगता है कि मैं आपके विपरीत एक सी ++ नौसिखिया हूं :) हालांकि, मैं टिप्पणी करने से पहले शीर्षक पढ़ने के बजाय पूरे प्रश्न को पढ़ने और इसके पीछे के उद्देश्य को समझने के लिए परेशान होगा। –

उत्तर

13
  1. std :: स्ट्रिंग, अपने स्वयं के स्मृति का प्रबंधन करता है, ताकि आप बनाते हैं, नकल, उन्हें आसानी से नष्ट कर सकते हैं।
  2. आप अपने स्वयं के बफर का उपयोग std :: string के रूप में नहीं कर सकते हैं।
  3. आपको किसी सी स्ट्रिंग/बफर को उस चीज़ पर पास करने की आवश्यकता है जो बफर के स्वामित्व को लेने की अपेक्षा करता है - जैसे कि तृतीय पक्ष सी लाइब्रेरी।
4

ठीक है, अगर तुम सिर्फ वर्ण की एक सरणी की जरूरत है, std :: स्ट्रिंग थोड़ा लाभ प्रदान करता है। लेकिन इसका सामना करो, यह मामला कितनी बार है? Std :: स्ट्रिंग जैसे अतिरिक्त कार्यक्षमता के साथ एक चार सरणी लपेटकर, आप कुछ परिचालनों के लिए बिजली और दक्षता दोनों प्राप्त करते हैं।

उदाहरण के लिए, वर्णों की सरणी की लंबाई निर्धारित करने के लिए सरणी में वर्णों को "गिनती" की आवश्यकता होती है। इसके विपरीत, एक std :: स्ट्रिंग इस विशेष कार्य के लिए एक कुशल संचालन प्रदान करता है। (https://stackoverflow.com/a/1467497/129622 देख)

  1. शक्ति, क्षमता और विवेक की तुलना में "बस" एक चार सरणी
  2. आप सिर्फ वर्ण की एक सरणी की जरूरत है
  3. बड़ा स्मृति पदचिह्न के लिए
2

3) सलाह हमेशा का उपयोग string का उपयोग सामान्य ज्ञान के चुटकी से लिया जाना चाहिए। स्ट्रिंग अक्षर const char[] हैं, और यदि आप const char* (उदाहरण के लिए std::ifstream::open()) के लिए एक शाब्दिक पास करते हैं तो std::string में इसे बिल्कुल लपेटने वाला कोई बिंदु नहीं है।

-1

सामान्य रूप से आपको हमेशा std :: स्ट्रिंग का उपयोग करना चाहिए, क्योंकि यह कम बग प्रवण है। ध्यान रखें, std :: स्ट्रिंग का स्मृति ओवरहेड महत्वपूर्ण है। हाल ही में मैंने std :: स्ट्रिंग ओवरहेड के बारे में कुछ प्रयोग किए हैं। आम तौर पर यह लगभग 48 बाइट्स है! लेख यहां है: http://jovislab.com/blog/?p=76

+1

एक दयालुता कि छोटे स्ट्रिंग अनुकूलन एक बड़ी बात है। – Puppy

+0

यह सब कार्यान्वयन पर निर्भर करता है। लेकिन व्यावहारिक रूप से, डिबग सामान के बिना, ओवरहेर्ड महत्वहीन होना चाहिए। –

+0

* यह * महत्वपूर्ण है। -ओ 2 और बिना किसी-जी के, जी ++ अभी भी ऑन-बाइट स्ट्रिंग के लिए 24 बाइट्स लेता है। मुझे लगता है कि यह विजुअल स्टूडियो के लिए है। – asanoki

1

एक char * मूल रूप से एक चरित्र के लिए एक सूचक है। सी सी अक्सर इस सूचक को किसी सरणी में पहले वर्ण को इंगित करता है।

एक std :: स्ट्रिंग एक कक्षा है जो एक वेक्टर की तरह है।आंतरिक रूप से, यह वर्णों की एक सरणी के भंडारण को संभालता है, और उपयोगकर्ता को कई सदस्य फ़ंक्शंस को संग्रहीत सरणी के साथ-साथ कई अधिभारित ऑपरेटरों में हेरफेर करने देता है।

Much more intuitive to use. 
Better searching, replacement, and manipulation functions. 
Reduced risk of segmentation faults. 

उदाहरण::

एक चार * पर एक std :: स्ट्रिंग का उपयोग करना

C backwards-compatibility. 
Performance (potentially). 
char*s have lower-level access. 

कारण:

कारण एक std :: स्ट्रिंग के ऊपर एक चार * उपयोग करने के लिए char * को किसी भी सरणी के साथ या गतिशील रूप से आवंटित चार सरणी के साथ संयोजन में उपयोग किया जाना चाहिए। आखिरकार, एक पॉइंटर बेकार है जब तक कि यह वास्तव में कुछ इंगित नहीं करता है। यह मुख्य रूप से सी कार्यक्रमों में प्रयोग किया जाता है:

char somebuffer[100] = "a string"; 
char* ptr = somebuffer; // ptr now points to somebuffer 
cout << ptr; // prints "a string" 
somebuffer[0] = 'b'; // change somebuffer 
cout << ptr; // prints "b string" 

सूचना है कि जब आप 'somebuffer' बदलने के लिए, 'ptr' भी बदल जाता है। ऐसा इसलिए है क्योंकि इस मामले में कुछ बफर वास्तविक स्ट्रिंग है। पीआरटी बस अंक/इसे संदर्भित करता है।

std :: स्ट्रिंग के साथ यह कम अजीब है: यहाँ

std::string a = "a string"; 
std::string b = a; 
cout << b; // prints "a string" 
a[0] = 'b'; // change 'a' 
cout << b; // prints "a string" (not "b string") 

, आपको लगता है कि बदलते देख सकते हैं 'एक', 'बी' को प्रभावित नहीं करता है क्योंकि 'बी' वास्तविक स्ट्रिंग है।

लेकिन वास्तव में, मुख्य अंतर यह है कि चार सरणी के साथ, आप स्मृति के प्रबंधन के लिए ज़िम्मेदार हैं, जबकि std :: string यह आपके लिए करता है। सी ++ में तारों पर चार सरणी का उपयोग करने के बहुत कम कारण हैं। 100 में से 99 बार आप स्ट्रिंग के साथ बेहतर हो जाते हैं।

जब तक आप स्मृति प्रबंधन और पॉइंटर्स को पूरी तरह से समझ नहीं लेते, बस अपने आप को कुछ सिरदर्द बचाएं और std :: string का उपयोग करें।

+0

मुझे सी तारों के बेहतर प्रदर्शन के बारे में दावा पर संदेह है। यह * कम मेमोरी ओवरहेड है जो महत्वपूर्ण हो सकता है यदि आपके पास बहुत छोटे स्ट्रिंग हैं (उदाहरण के लिए पार्सिंग या बायोइनफॉरमैटिक्स में, जहां 'std :: string' निषिद्ध हो सकता है)। –

+0

char का उपयोग करके * आपको दृश्यों के पीछे "क्या हो रहा है" पर अधिक नियंत्रण देता है, जिसका अर्थ है कि यदि आपको आवश्यकता हो तो आप प्रदर्शन को ट्यून कर सकते हैं। –

1

सी ++ में सी-शैली तारों पर std :: स्ट्रिंग का उपयोग क्यों करना चाहिए?

मुख्य कारण यह है कि यह आपको स्ट्रिंग डेटा के जीवनकाल के प्रबंधन से मुक्त करता है। आप केवल तारों के रूप में तारों का इलाज कर सकते हैं और संकलक/पुस्तकालय को स्मृति के प्रबंधन के बारे में चिंता करने दें।

मैन्युअल रूप से स्मृति आवंटन और जीवनकाल का प्रबंधन करना कठिन और त्रुटि प्रवण है।

# 1 में उल्लिखित अभ्यास के नुकसान (यदि कोई हैं) क्या हैं?

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

आप सावधान आपको अनावश्यक डेटा कॉपी करने का एक बहुत (एक गैर refcounted कार्यान्वयन में) या संदर्भ गिनती में गड़बड़ी (एक refcounted कार्यान्वयन में)

एक मिश्रित-भाषा परियोजना में साथ खत्म हो सकता है नहीं कर रहे हैं किसी भी फ़ंक्शन जिसका तर्क std :: स्ट्रिंग या किसी भी डेटा संरचना का उपयोग करता है जिसमें std :: string शामिल है, सीधे अन्य भाषाओं से उपयोग नहीं किया जा सकेगा।

परिदृश्य क्या हैं जहां # 1 में उल्लिखित सलाह के विपरीत एक अच्छा अभ्यास है?

अलग अलग लोगों ने इस पर अलग राय होगा लेकिन IMO

  • समारोह बहस में "स्थिरांक चार *" तार गुजर के लिए एक अच्छा विकल्प है क्योंकि यह unnessacery नकल/refcouning से बचा जाता है और के बारे में फोन करने वाले लचीलापन प्रदान करता है है वे क्या पास करते हैं।
  • अन्य भाषाओं के साथ बातचीत में उपयोग की जाने वाली चीज़ों के लिए आपके पास सी-स्टाइल स्ट्रिंग का उपयोग करने के लिए बहुत कम विकल्प है।
  • जब आपके पास ज्ञात लंबाई सीमा है तो यह निश्चित आकार के सरणी का उपयोग करने के लिए तेज़ हो सकता है।
  • जब बहुत लंबे तार के साथ काम कर यह एक निर्माण कि निश्चित रूप से करने के बजाय refcounted जाएगा की नकल की है (जैसे एक चरित्र सरणी एक shared_ptr में लिपटे के रूप में) या वास्तव में पूरी तरह डेटा संरचना
एक अलग प्रकार का उपयोग करने के लिए उपयोग करने के लिए बेहतर हो सकता है