2012-01-12 7 views
26

मेरा कोड कुछ बार अक्सर सी ++ तारों को CStrings में परिवर्तित करता है, और मुझे आश्चर्य है कि मूल स्ट्रिंग को स्टैक पर आवंटित किया गया है, क्या सीएसटींग को स्टैक पर भी आवंटित किया जाएगा? उदाहरण के लिए:string.c_str() deallocation आवश्यक है?

string s = "Hello world"; 
char* s2 = s.c_str(); 

s2 या ढेर में ढेर पर आवंटित किया जाएगा? दूसरे शब्दों में, क्या मुझे s2 को हटाना होगा?

इसके विपरीत, यदि मैं इस कोड है:

string s = new string("Hello, mr. heap..."); 
char* s2 = s.c_str(); 

s2 अब, ढेर पर होगा के रूप में अपने मूल ढेर पर था?

स्पष्टीकरण के लिए, जब मैं पूछता हूं कि s2 ढेर पर है, तो मुझे पता है कि सूचक ढेर पर है। मैं पूछ रहा हूं कि पर यह इंगित करता है कि ढेर या ढेर पर होगा।

उत्तर

32
string s = "Hello world"; 
char* s2 = s.c_str(); 

s2 ढेर में ढेर पर आवंटित किया जाएगा, या? दूसरे शब्दों में ... क्या मुझे एस 2 को हटाना होगा?

s2 ढेर पर है, हाँ। लेकिन, यह एक चरित्र के लिए एक सूचक है (जो इस मामले में s की टेक्स्ट सामग्री के ASCIIZ प्रतिनिधित्व में पहला अक्षर होता है)। वह पाठ स्वयं ही है जहां s ऑब्जेक्ट उस प्रतिनिधित्व को बनाने की तरह महसूस किया गया।क्रियान्वयन लेकिन वे चाहते है कि ऐसा करने के लिए अनुमति दी जाती है, लेकिन std::string के लिए महत्वपूर्ण कार्यान्वयन विकल्प है कि क्या वे एक "छोटी स्ट्रिंग अनुकूलन" बहुत ही कम तार s वस्तु में और भले ही प्रत्यक्ष रूप एम्बेड करने के लिए अनुमति देता है प्रदान करना है "हैलो दुनिया", इतना छोटा है कि अनुकूलन का लाभ उठाने:

  • यदि हां, तो फिर s2s
  • अन्यथा अंदर आबंटित स्मृति ढेर को इंगित होता है, s अंदर वहाँ मुक्त-स्टोर करने के लिए/ढेर आबंटित स्मृति एक सूचक होगा जिसमें "हैलो दुनिया \ 0 "सामग्री जिसका पता .c_str() द्वारा वापस किया जाएगा, और एस 2 उस मान की एक प्रति होगी।

ध्यान दें कि c_str()const है, इसलिए के लिए अपने कोड आप const char* s2 = ... को बदलने की जरूरत है संकलित करने के लिए।

आप s2, कोई हटाने की आवश्यकता नहीं है। आंकड़ों के जो अंक अभी भी स्वामित्व और s वस्तु द्वारा किया जाता है एस 2, किसी भी कॉल द्वारा अवैध हो जाएगा s की const तरीकों गैर करने के लिए या s से दायरे से बाहर जा रहा है।

string s = new string("Hello, mr. heap..."); 
char* s2 = s.c_str(); 

अब S2 करेंगे, ढेर पर हो के रूप में अपने मूल ढेर पर था?

इस कोड संकलन नहीं करता है, s के रूप में एक सूचक नहीं है और एक स्ट्रिंग string(std::string*) की तरह एक निर्माता नहीं है। आप या तो के लिए इसे बदल सकता है:

string* s = new string("Hello, mr. heap..."); 

... या ...

string s = *new string("Hello, mr. heap..."); 

बाद एक स्मृति रिसाव बनाता है और कोई उपयोगी उद्देश्य में कार्य करता है, तो के पूर्व मान लें। तब:

char* s2 = s.c_str(); 

... बनने के लिए की जरूरत है ...

char* s2 = s->c_str(); 

अब S2 करेंगे, ढेर पर हो के रूप में अपने मूल ढेर पर था?

हां। अन्यथा

  • वहाँ एक छोटी स्ट्रिंग अनुकूलन बफर s अंदर करने के लिए जो c_str() एक सूचक पैदावार, यह ढेर पर होना चाहिए है

    • भले ही,: सभी स्थितियों में, विशेष रूप से अगर s ही ढेर पर है, तो यदि s पाठ को संग्रहीत करने के लिए आगे की स्मृति के लिए एक सूचक का उपयोग करता है, तो उस मेमोरी को ढेर से भी आवंटित किया जाएगा।

    लेकिन फिर से, यहां तक ​​कि यकीन के लिए जानते हुए भी कि ढेर-आबंटित स्मृति को s2 अंक, अपने कोड है कि स्मृति पुनःआवंटन की जरूरत नहीं है - यह स्वचालित रूप से किया जाएगा जब s हटा दी जाती है:

    string* s = new string("Hello, mr. heap..."); 
    const char* s2 = s->c_str(); 
    ...use s2 for something... 
    delete s; // "destruct" s and deallocate the heap used for it... 
    
    के

    बेशक, आमतौर पर string s("xyz"); का उपयोग करने के लिए बेहतर होता है जब तक कि आपको स्थानीय दायरे से अधिक जीवनकाल की आवश्यकता न हो, और std::unique_ptr<std::string> या std::shared_ptr<std::string> अन्यथा।

  • 12

    c_str()string वस्तु में एक आंतरिक बफर करने के लिए एक सूचक रिटर्न - क्या तुमने कभी नहीं free()/delete करते हैं।

    यह केवल तब तक वैध है जब तक string यह बिंदु में है। इसके अतिरिक्त यदि आप string ऑब्जेक्ट की गैर-कॉन्स्ट विधि को कॉल करते हैं तो यह अब वैध होने की गारंटी नहीं है।

    http://www.cplusplus.com/reference/string/string/c_str/

    +0

    दिलचस्प, तो, आप कभी भी char * को मुक्त नहीं करेंगे क्योंकि ऐसा करने से स्ट्रिंग में आंतरिक डेटा मुक्त हो जाएगा? c_str() सचमुच वही पता रखता है जो स्ट्रिंग का उपयोग कर रहे वास्तविक डेटा के रूप में होता है? .c_str() पर एकाधिक कॉल उसी पते को उसी तरह वापस कर देंगे? (बस स्पष्टीकरण इसलिए मुझे पता है कि मैं समझता हूं) –

    +0

    @Georges उन सवालों में से कुछ का जवाब इस बात पर निर्भर करता है कि आप नवीनतम मानक या पुराने मानक का उपयोग कर रहे हैं या नहीं। आप यह स्पष्ट करना चाहते हैं कि आप किसमें रुचि रखते हैं। –

    +0

    @ आर। मार्टिन्होफर्नैंड्स बेहतर मानक के साथ जाएं। यह जानना दिलचस्प होगा कि यह मानक कितना हालिया है –

    0

    यह निर्भर करता है (नीचे टिप्पणी के आधार पर स्पष्टता के लिए संपादित)। अगर मुझे सही याद है, तो CString इनपुट स्ट्रिंग की एक प्रति बनाता है, इसलिए नहीं, आपको कोई विशेष ढेर आवंटन दिनचर्या की आवश्यकता नहीं होगी।

    4

    std::string::c_str()const char* देता है, char * नहीं। यह एक बहुत अच्छा संकेत है कि आपको इसे मुक्त करने की आवश्यकता नहीं है। उदाहरण के लिए मेमोरी प्रबंधित की जाती है (उदाहरण के लिए this link में कुछ विवरण देखें), इसलिए स्ट्रिंग इंस्टेंस मान्य होने पर यह केवल मान्य है।

    +6

    पॉइंट-टू ऑब्जेक्ट का कॉन्स-क्वालीफिकेशन बिल्कुल संकेत नहीं है कि यह नहीं करता है कॉलर द्वारा मुक्त होने की जरूरत नहीं है। –

    +0

    @JamesMcNellis: वस्तुओं के लिए सच है। लेकिन एक 'char * 'बिल्कुल एक वस्तु नहीं है, केवल एक सादा सी प्रकार है। और सादे सी स्थिरता में आम तौर पर यह संकेत करने के लिए प्रयोग किया जाता है कि "आपके पास इस स्मृति का स्वामित्व नहीं है" (क्योंकि 'मुक्त (3)' एक गैर-कॉन्स्ट पॉइंटर लेता है)। – vanza

    +0

    @JamesMcNellis: ऐसे कार्यों के कौन से उदाहरण हैं? मैं इसे बहुत भ्रमित मानता हूं और बहुत स्पष्ट रूप से टिप्पणी करता हूं जब कॉलर द्वारा लौटाए जाने वाले 'कॉन्स' पॉइंटर को इंगित करने की आवश्यकता होती है। – leftaroundabout

    2

    s2 तब तक मान्य होगा जब तक s गुंजाइश में बनी रहेगी। यह स्मृति के लिए एक सूचक है कि s का मालिक है। उदाहरण देखें this MSDN documentation: "स्ट्रिंग का सीमित जीवनकाल है और इसका वर्ग वर्ग स्ट्रिंग है।"

    आप स्ट्रिंग हेरफेर के लिए एक कारखाने के रूप में एक समारोह के अंदर std::string का उपयोग करें, और उसके बाद सी शैली तार वापस करना चाहते हैं, तो आप वापसी मान के लिए ढेर भंडारण का आवंटन करना चाहिए। malloc या new का उपयोग करके स्थान प्राप्त करें, और उसके बाद s.c_str() की सामग्री कॉपी करें।

    1

    क्या एस 2 स्टैक पर या ढेर में आवंटित किया जाएगा?

    या तो हो सकता है। उदाहरण के लिए, यदि std::string वर्ग छोटे स्ट्रिंग ऑप्टिमाइज़ेशन करता है, तो डेटा एसएसओ थ्रेसहोल्ड से नीचे है, और अन्यथा ढेर पर डेटा स्टैक पर रहता है। (और यह सब मानते हैं कि std::string ऑब्जेक्ट स्वयं ढेर पर है।)

    मैं s2 नष्ट करने के लिए की आवश्यकता होगी?

    नहीं, c_str द्वारा लौटाई गई वर्ण सरणी वस्तु स्ट्रिंग ऑब्जेक्ट के स्वामित्व में है।

    क्या एस 2 अब ढेर पर होगा, क्योंकि इसकी उत्पत्ति ढेर पर थी?

    इस मामले में डेटा एसएसओ करते समय भी वैसे ही ढेर में रहता है। लेकिन std::string ऑब्जेक्ट को गतिशील रूप से आवंटित करने का कोई कारण नहीं है।

    +0

    बहुत विस्तृत उत्तर के लिए धन्यवाद :) –

    4

    सबसे पहले, यहां तक ​​कि अपने मूल स्ट्रिंग, ढेर पर आवंटित नहीं किया गया है के रूप में आप पर विश्वास करने लगते हैं। कम से कम पूरी तरह से नहीं। यदि आपका string s स्थानीय चर के रूप में घोषित किया गया है, तो केवल string ऑब्जेक्ट स्वयं "ढेर पर आवंटित" है। उस स्ट्रिंग ऑब्जेक्ट का नियंत्रित अनुक्रम कहीं और आवंटित किया जाता है। आपको यह नहीं पता होना चाहिए कि इसे आवंटित किया गया है, लेकिन ज्यादातर मामलों में इसे ढेर पर आवंटित किया जाता है। अर्थात। आपके पहले उदाहरण में s द्वारा संग्रहीत वास्तविक स्ट्रिंग "Hello world" आमतौर पर ढेर पर आवंटित की जाती है, भले ही आप अपना s कहां घोषित करें।

    दूसरे, के बारे में c_str()

    सी ++ (सी ++ 98) c_str के मूल विनिर्देशन में आम तौर पर कहीं भी आवंटित एक स्वतंत्र बफर में एक सूचक लौटा दिया। दोबारा, आपको यह नहीं पता होना चाहिए कि इसे आवंटित किया गया है, लेकिन सामान्य स्थिति में इसे ढेर पर आवंटित किया जाना था। std::string के अधिकांश कार्यान्वयन ने सुनिश्चित किया कि उनका नियंत्रित अनुक्रम हमेशा शून्य-समाप्त हो गया था, इसलिए उनके c_str ने नियंत्रित अनुक्रम में प्रत्यक्ष सूचक लौटा दिया।

    सी ++ (सी ++ 11) के नए विनिर्देशन में अब यह आवश्यक है कि c_str नियंत्रित अनुक्रम में प्रत्यक्ष सूचक लौटाता है।

    दूसरे शब्दों में, सामान्य स्थिति में c_str का परिणाम स्थानीय std::string ऑब्जेक्ट्स के लिए भी एक ढेर-आवंटित स्मृति को इंगित करेगा। आपका पहला उदाहरण उस संबंध में आपके दूसरे उदाहरण से अलग नहीं है। हालांकि, किसी भी मामले में c_str() द्वारा निर्धारित स्मृति आपके स्वामित्व में नहीं है। आपको इसे रद्द नहीं करना है। आपको यह भी पता नहीं होना चाहिए कि इसे आवंटित किया गया है।

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