2008-10-11 11 views
70

मैंने कई स्थानों को पढ़ा है कि c_str() और data() (एसटीएल और अन्य कार्यान्वयन में) के बीच का अंतर यह है कि c_str()data() नहीं है, जबकि हमेशा शून्य समाप्त हो जाता है। जहां तक ​​मैंने वास्तविक कार्यान्वयन में देखा है, वे या तो वही करते हैं या data()c_str() पर कॉल करते हैं।स्ट्रिंग c_str() बनाम डेटा()

मुझे यहां क्या याद आ रही है? कौन सा परिदृश्य किस परिदृश्य में उपयोग करने के लिए अधिक सही है?

उत्तर

80

दस्तावेज़ीकरण सही है। यदि आप एक शून्य समाप्त स्ट्रिंग चाहते हैं तो c_str() का उपयोग करें।

कार्यान्वयन c_str() के मामले में data() लागू करने के लिए happend यदि आप चिंता है, अभी भी data() उपयोग करने के लिए अगर आप कुछ कार्यान्वयन में यह तुलना में बेहतर प्रदर्शन करने के लिए बाहर हो सकते हैं अशक्त समाप्त किया जा स्ट्रिंग की जरूरत नहीं है, नहीं है c_str()।

तारों को चरित्र डेटा से बनी जरूरी नहीं है, वे किसी भी प्रकार के तत्वों से बना सकते हैं। उन मामलों में data() अधिक सार्थक है। मेरी राय में c_str() केवल तभी उपयोगी होता है जब आपकी स्ट्रिंग के तत्व चरित्र आधारित होते हैं।

अतिरिक्त: सी ++ 11 में, दोनों कार्यों को एक जैसा होना आवश्यक है। यानी data अब शून्य-समाप्त होने की आवश्यकता है। cppreference के अनुसार: "लौटा सरणी शून्य-समाप्त हो गई है, यानी, डेटा() और c_str() एक ही कार्य करता है।"

16

यह भी पता है कि आपने देखा है कि वे वही करते हैं, या वह .data() कॉल .c_str(), यह मानना ​​सही नहीं है कि यह अन्य कंपाइलरों के लिए होगा। यह भी संभव है कि आपका कंपाइलर भविष्य की रिलीज के साथ बदल जाएगा।

2 कारणों std :: स्ट्रिंग का उपयोग करना:

std :: स्ट्रिंग दोनों पाठ और मनमाने ढंग से बाइनरी डेटा के लिए इस्तेमाल किया जा सकता है।

//Example 1 
//Plain text: 
std::string s1; 
s1 = "abc"; 

//Example 2 
//Arbitrary binary data: 
std::string s2; 
s2.append("a\0b\0b\0", 6); 

आप .c_str() विधि का उपयोग करके ऐसी उदाहरण के रूप में अपने स्ट्रिंग का उपयोग कर रहे चाहिए 1.

आप .data() विधि का उपयोग करके ऐसी उदाहरण 2. नहीं के रूप में अपने स्ट्रिंग का उपयोग कर रहे चाहिए क्योंकि इन मामलों में .c_str() का उपयोग करना डरावना है, लेकिन क्योंकि यह अधिक स्पष्ट है कि आप अपने कोड की समीक्षा करने वाले अन्य लोगों के लिए बाइनरी डेटा के साथ काम कर रहे हैं।

.data()

निम्नलिखित कोड गलत है और अपने कार्यक्रम में एक segfault कारण बन सकता है का उपयोग कर के साथ संभावित ख़तरा:

std::string s; 
s = "abc"; 
char sz[512]; 
strcpy(sz, s.data());//This could crash depending on the implementation of .data() 

क्यों यह आम कार्यान्वयन .data बनाने के लिए के लिए है() और .c_str() वही काम करते हैं?

क्योंकि ऐसा करने के लिए यह अधिक कुशल है। .data() को कुछ ऐसा करने का एकमात्र तरीका जो निरस्त नहीं है, को .c_str() या .data() को उनके आंतरिक बफर की प्रतिलिपि बनाना होगा, या केवल 2 बफर का उपयोग करना होगा। एक एकल शून्य समाप्त बफर होने का मतलब हमेशा है कि आप std :: स्ट्रिंग को लागू करते समय हमेशा एक आंतरिक बफर का उपयोग कर सकते हैं।

+6

वास्तव में, .data के बिंदु() है कि यह आंतरिक बफर नकल नहीं करनी चाहिए है। इसका मतलब है कि कार्यान्वयन को जब तक इसकी आवश्यकता न हो तब तक एक char को बर्बाद नहीं करना पड़ेगा। आप कभी भी दो बफर नहीं चाहते हैं: यदि आप कॉल करते हैं .c_str(), बफर में \ 0 संलग्न करें। .data() अभी भी उस बफर को वापस कर सकता है। – MSalters

+1

पूरी तरह से सहमत है यह 2 बफर का उपयोग करने के लिए हास्यास्पद होगा। आप कैसे जानते हैं कि यही कारण है कि डेटा का इरादा था? –

+0

@ BrianR.Bondy मैं इस कोड की कोशिश की: ..ऑटो स्ट्र = स्ट्रिंग {"टेस्ट \ 0 स्ट्रिंग!" }; cout << "डेटा:" << str.data() << endl; आउटपुट "टेस्ट" है और पूरी स्ट्रिंग नहीं है, मैंने गलत क्या किया? – programmer

1

उद्धरण ANSI ISO IEC 14882 2003 (सी ++ 03 मानक) से:

21.3.6 basic_string string operations [lib.string.ops] 

    const charT* c_str() const; 

    Returns: A pointer to the initial element of an array of length size() + 1 whose first size() elements 
equal the corresponding elements of the string controlled by *this and whose last element is a 
null character specified by charT(). 
    Requires: The program shall not alter any of the values stored in the array. Nor shall the program treat the 
returned value as a valid pointer value after any subsequent call to a non-const member function of the 
class basic_string that designates the same object as this. 

    const charT* data() const; 

    Returns: If size() is nonzero, the member returns a pointer to the initial element of an array whose first 
size() elements equal the corresponding elements of the string controlled by *this. If size() is 
zero, the member returns a non-null pointer that is copyable and can have zero added to it. 
    Requires: The program shall not alter any of the values stored in the character array. Nor shall the program 
treat the returned value as a valid pointer value after any subsequent call to a non- const member 
function of basic_string that designates the same object as this. 
2

यह पहले से ही उत्तर दिया गया है, उद्देश्य पर कुछ नोट: कार्यान्वयन की स्वतंत्रता।

std::string संचालन - जैसे पुनरावृत्ति, concatenation और तत्व उत्परिवर्तन - शून्य टर्मिनेटर की आवश्यकता नहीं है। जब तक आप एक समारोह एक शून्य समाप्त स्ट्रिंग की उम्मीद करने के लिए string गुजरती हैं, यह ज़रूरी नहीं है।

यह सब स्ट्रिंग्स को वास्तविक स्ट्रिंग डेटा साझा करने के कार्यान्वयन की अनुमति देगा: string::substr आंतरिक स्ट्रिंग डेटा की प्रतिलिपि (और अतिरिक्त आवंटन) से बचने के लिए आंतरिक स्ट्रिंग डेटा, और प्रारंभ/अंत सीमा के संदर्भ में आंतरिक रूप से संदर्भ रख सकता है। कार्यान्वयन प्रतिलिपि को तब तक रोक देगा जब तक कि आप c_str को कॉल न करें या किसी भी स्ट्रिंग को संशोधित न करें। अगर शामिल किए गए स्ट्रिंग्स को पढ़ा जाता है तो कोई प्रतिलिपि नहीं बनाई जाएगी।

(कॉपी-ऑन-राइट कार्यान्वयन बहुप्रचारित वातावरण में बहुत मजेदार नहीं है, साथ ही सामान्य स्मृति/आवंटन बचत आज अधिक जटिल कोड के लायक नहीं है, इसलिए यह शायद ही कभी किया जाता है)।


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

20

C++11/C++0x, data() और c_str() अब अलग नहीं है। और इस प्रकार data() को भी अंत में एक शून्य समाप्ति की आवश्यकता है।

21.4.7.1 basic_string accessors [string.accessors]

const charT* c_str() const noexcept;

const charT* data() const noexcept;

1 रिटर्न: [0,size()] में प्रत्येक i के लिए एक सूचक पी ऐसी है कि p + i == &operator[](i)


21.4.5 basic_string तत्व पहुंच [string.access]

const_reference operator[](size_type pos) const noexcept;

1 आवश्यक है: < = आकार() स्थिति। 2 रिटर्न: *(begin() + pos) if pos < size(), मूल्य charT(); साथ प्रकार टी का एक उद्देश्य के लिए अन्यथा एक संदर्भ संदर्भित मूल्य मोदी फाई एड नहीं होगा।

+0

क्या होगा यदि स्ट्रिंग गैर-वर्ण डेटा से बना है, जो स्ट्रिंग डेटा AFAIK के लिए कानूनी है, जिसमें शून्य शामिल है? – taz

+3

@taz बाइनरी डेटा संग्रहीत करते समय भी, सी ++ 11 की आवश्यकता है कि 'std :: string' पीछे की '' 0'' के लिए अतिरिक्त 'char' आवंटित करें। जब आप 'std :: string s (" \ 0 ") करते हैं;', दोनों 's.data() [0] 'और' s.data() [1] 'को 0 का मूल्यांकन करने की गारंटी है। – bcrist

 संबंधित मुद्दे

  • कोई संबंधित समस्या नहीं^_^