स्ट्रिंग c_str () बनाम डेटा ()


102

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

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

जवाबों:


105

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

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

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

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


4
अतिरिक्त 2: C ++ 17 के बाद, अब के लिए एक गैर-कॉन्स्टेबल अधिभार भी है .data(), इसलिए वे गैर-स्थिर स्ट्रिंग्स के लिए समान नहीं हैं।
डिडुप्लिकेटर

29

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

21.4.7.1 एक्सेसर्स basic_string[string.accessors]

const charT* c_str() const noexcept;

const charT* data() const noexcept;

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


21.4.5 बुनियादी_स्ट्रिंग तत्व पहुंच [string.access]

const_reference operator[](size_type pos) const noexcept;

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


क्या होगा यदि स्ट्रिंग गैर-चरित्र डेटा से बना है, जो स्ट्रिंग डेटा AFAIK के लिए कानूनी है, जिसमें अशक्त भी शामिल है?
ताज़ जूल

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

19

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

Std :: string का उपयोग करने के 2 कारण:

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

//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 () का उपयोग करके संभावित नुकसान

निम्न कोड गलत है और आपके प्रोग्राम में सेगफॉल्ट का कारण बन सकता है:

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__ () या (.data) या केवल 2 बफ़र्स का उपयोग करना होगा। एक एकल अशक्त बफ़र होने का हमेशा मतलब है कि आप हमेशा एक आंतरिक बफर का उपयोग कर सकते हैं जब std :: string को कार्यान्वित किया जाता है।


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

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

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

अंतिम भाग गलत है, डेटा और c_str 0-टर्मिनेट हुए बिना एक ही बफर का उपयोग कर सकता है - c_str केवल पहली कॉल पर 0 जोड़ सकता है।
मोनिका

हेड्स अप, सी ++ 11 मेड .डेटा () .c_str () के लिए एक उपनाम
हैनशैरिक

3

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

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

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

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


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


2

से उद्धरण ANSI ISO IEC 14882 2003(C ++ 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

सभी पिछले हंगामे सम्‍मिलित हैं, लेकिन मैं यह भी जोड़ना चाहूंगा कि c ++ 17 में शुरू करके, str.data () const char * के बजाय एक char * लौटाता है।


1
दोनों constऔर non-constअधिभार C ++ 17 के बाद से उपलब्ध हैं।
गुप्त
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.