दिलचस्प पोस्ट
Scanf का उपयोग करके रिक्त स्थान को कैसे दर्ज किया जा सकता है? अगर जावा में बयान की लंबी सूची PHP परियोजनाओं के लिए एक तैनाती / बिल्ड / सीआई चक्र सेट करना स्ट्रॉप्स में सुई के रूप में एक सरणी का उपयोग करना अधिकतम अपलोड फ़ाइल आकार बदलें अस्थायी बिंदु अंकगणित सटीक नतीजे का उत्पादन नहीं करते इकाई परीक्षण सी # में निजी तरीकों फ़ॉर्म को पृष्ठ रिफ्रेश के बिना PHP के लिए AJAX पासिंग डेटा के साथ सबमिट करें MySQL स्प्लिट कॉमा से अलग स्ट्रिंग इन अस्थायी तालिका में यूट्यूब वीडियो WebView में नहीं खेल रहा है – एंड्रॉइड Git दूरस्थ: त्रुटि: घातक: प्रोटोकॉल त्रुटि: बुरा रेखा लंबाई वर्ण: Unab एकाधिक जीआईटी रिपॉजिटरी के संयोजन जावास्क्रिप्ट के जरिए एफएफ और क्रोम में मैं डिफ़ॉल्ट होमपेज कैसे सेट कर सकता हूं? विशिष्ट यूआरएल खोलने के लिए ब्राउजर पर एक इरादा भेजना एक्स-यूए-संगत IE = बढ़त पर सेट है, लेकिन यह संगतता मोड को अभी भी बंद नहीं करता है

स्ट्रिंग स्ट्रीम, स्ट्रिंग, और चार * रूपांतरण भ्रम

मेरा प्रश्न नीचे उबला जा सकता है, जहां स्ट्रिंग स्ट्रिंग से stringstream.str().c_str() स्मृति में रहते हैं, और यह const char* को क्यों नहीं सौंपा जा सकता है?

यह कोड उदाहरण यह बता सकता है कि मैं क्या कर सकता हूं

 #include <string> #include <sstream> #include <iostream> using namespace std; int main() { stringstream ss("this is a string\n"); string str(ss.str()); const char* cstr1 = str.c_str(); const char* cstr2 = ss.str().c_str(); cout << cstr1 // Prints correctly << cstr2; // ERROR, prints out garbage system("PAUSE"); return 0; } 

धारणा है कि stringstream.str().c_str() एक const char* को असाइन किया जा सकता है जिससे एक बग हुआ जिससे मुझे ट्रैक करने में थोड़ी देर लगे।

बोनस अंक के लिए, कोई भी समझा सकता है कि cout स्टेटमेंट की जगह के साथ क्यों

 cout << cstr // Prints correctly << ss.str().c_str() // Prints correctly << cstr2; // Prints correctly (???) 

तार को सही ढंग से प्रिंट करता है?

मैं दृश्य स्टूडियो 2008 में संकलित कर रहा हूँ

वेब के समाधान से एकत्रित समाधान "स्ट्रिंग स्ट्रीम, स्ट्रिंग, और चार * रूपांतरण भ्रम"

stringstream.str() एक अस्थायी स्ट्रिंग ऑब्जेक्ट देता है जो पूर्ण अभिव्यक्ति के अंत में नष्ट हो गया है। यदि आपको सी ( stringstream.str().c_str() से एक सी स्ट्रिंग के लिए एक सूचक मिलता है, तो यह एक स्ट्रिंग को इंगित करेगा जो स्टेटमेंट समाप्त होने पर हटाया जाता है। यही कारण है कि आपका कोड कचरा प्रिंट करता है।

आप उस अस्थायी स्ट्रिंग ऑब्जेक्ट को किसी अन्य स्ट्रिंग ऑब्जेक्ट की प्रतिलिपि बना सकते हैं और उस से सी स्ट्रिंग ले सकते हैं:

 const std::string tmp = stringstream.str(); const char* cstr = tmp.c_str(); 

ध्यान दें कि मैंने अस्थायी स्ट्रिंग cstr बना दिया है, क्योंकि इसमें कोई भी परिवर्तन हो सकता है क्योंकि इसे पुन: आवंटित किया जा सकता है और इस प्रकार cstr अमान्य होता है। यह सभी के लिए कॉल के परिणाम को cstr न करने के लिए सुरक्षित है और पूरी अभिव्यक्ति के अंत तक केवल cstr उपयोग करें:

 use_c_str( stringstream.str().c_str() ); 

बेशक, उत्तरार्द्ध आसान नहीं हो सकता है और नकल बहुत महंगा हो सकता है इसके बजाय आप एक अस्थायी संदर्भ को अस्थायी रूप से बाँध सकते हैं। यह संदर्भ के जीवनकाल में अपने जीवनकाल का विस्तार करेगा:

 { const std::string& tmp = stringstream.str(); const char* cstr = tmp.c_str(); } 

आईएमओ सबसे अच्छा समाधान है दुर्भाग्य से यह बहुत अच्छी तरह से ज्ञात नहीं है

आप क्या कर रहे हैं एक अस्थायी बना रहा है यह अस्थायी कंपाइलर द्वारा निर्धारित एक क्षेत्र में मौजूद है, जैसे कि यह कहाँ जा रहा है की आवश्यकताओं को पूरा करने के लिए पर्याप्त है

जैसे ही बयान const char* cstr2 = ss.str().c_str(); पूरा हो गया है, कंपाइलर को अस्थायी स्ट्रिंग को चारों ओर रखने का कोई कारण नहीं है, और इसे नष्ट कर दिया गया है, और इस तरह आपका const char * फ्री मेमोरी की ओर इशारा कर रहा है

आपका बयान string str(ss.str()); का अर्थ है कि अस्थायी string वेरिएबल string लिए कन्स्ट्रक्टर में उपयोग किया जाता है जो आपने स्थानीय स्टैक पर रख दिया है, और जब तक आप अपेक्षा करते हैं तब तक रहता है: ब्लॉक के अंत तक या आपके द्वारा लिखे गए फ़ंक्शन तक। इसलिए जब आप cout कोशिश करते हैं तो const char * अभी भी अच्छी मेमोरी है

इस पंक्ति में:

 const char* cstr2 = ss.str().c_str(); 

ss.str() की सामग्री की एक प्रतिलिपि बनायेगी। जब आप एक ही पंक्ति पर c_str() कहते हैं, तो आप वैध डेटा का संदर्भ लेंगे, लेकिन उस पंक्ति के बाद स्ट्रिंग को नष्ट कर दिया जाएगा, जिससे आपका char* अनावृत स्मृति को इंगित करेगा

ss.str() आरंभ होने के बाद ss.str() अस्थायी नष्ट हो गया है। इसलिए जब आप इसे cout साथ प्रिंट करते हैं, तो c-string जो कि std::string अस्थायी के साथ संबद्ध था लंबे समय से नष्ट हो गया है, और इस तरह आप भाग्यशाली होंगे यदि यह क्रैश और आग्रह करता है, और भाग्यशाली नहीं है अगर यह कचरा प्रिंट करता है या दिखाई देता है काम।

 const char* cstr2 = ss.str().c_str(); 

सी-स्ट्रिंग जहां cstr1 इंगित करता है, हालांकि, एक स्ट्रिंग के साथ जुड़ा हुआ है जो अभी भी उस समय मौजूद होता है जब आप cstr1 करते हैं – इसलिए यह सही रूप से परिणाम प्रिंट करता है।

निम्नलिखित कोड में, प्रथम cstr सही है (मुझे लगता है कि यह वास्तविक कोड में cstr1 है?)। दूसरा, अस्थायी स्ट्रिंग ऑब्जेक्ट ss.str() जुड़े सी स्ट्रिंग प्रिंट करता है। वस्तु पूर्ण अभिव्यक्ति के मूल्यांकन के अंत में नष्ट हो जाती है जिसमें यह प्रकट होता है। पूर्ण-अभिव्यक्ति संपूर्ण cout << ... अभिव्यक्ति है – इसलिए जब सी-स्ट्रिंग आउटपुट है, तो संबंधित स्ट्रिंग ऑब्जेक्ट अभी भी मौजूद है। cstr2 – यह शुद्ध बुराई है कि यह सफल होता है यह सबसे संभवतः आंतरिक रूप से नए अस्थायी स्थान के लिए एक ही भंडारण स्थान को चुनता है जो इसे पहले से ही cstr2 को प्रारंभ करने के लिए अस्थायी रूप से चुना गया था यह भी दुर्घटना हो सकता है

 cout << cstr // Prints correctly << ss.str().c_str() // Prints correctly << cstr2; // Prints correctly (???) 

c_str() की वापसी आमतौर पर केवल आंतरिक स्ट्रिंग बफर को इंगित करेगी – लेकिन यह एक आवश्यकता नहीं है स्ट्रिंग एक बफर बना सकती है, अगर इसके आंतरिक क्रियान्वयन उदाहरण के लिए निकटतम नहीं है (यह अच्छी तरह से संभव है – लेकिन अगले सी ++ मानक में, स्ट्रिंग्स को कॉन्सीग्यू से संग्रहीत करने की आवश्यकता है)।

जीसीसी में, स्ट्रिंग संदर्भ गणना और प्रति-पर-लिखने का उपयोग करते हैं इस प्रकार, आपको पता चल जाएगा कि निम्नलिखित सत्य हैं (यह कम से कम मेरे जीसीसी संस्करण पर है)

 string a = "hello"; string b(a); assert(a.c_str() == b.c_str()); 

दो स्ट्रिंग्स यहां समान बफर साझा करते हैं। उस समय आप उनमें से एक को बदलते हैं, बफर की प्रतिलिपि बनाई जाएगी और प्रत्येक अपनी अलग प्रतिलिपि रखेगा। अन्य स्ट्रिंग कार्यान्वयन कुछ अलग करती है, यद्यपि।

Sts :: string ऑब्जेक्ट ss.str () द्वारा वापस आ गया है एक अस्थायी ऑब्जेक्ट है जो अभिव्यक्ति तक सीमित रहता है। इसलिए आप कचरा हो बिना एक अस्थायी ऑब्जेक्ट पर एक पॉइंटर निर्दिष्ट नहीं कर सकते।

अब, एक अपवाद है: यदि आप अस्थायी वस्तु प्राप्त करने के लिए एक const संदर्भ का उपयोग करते हैं, तो यह एक व्यापक जीवन काल के लिए उपयोग करने के लिए कानूनी है। उदाहरण के लिए आपको करना चाहिए:

 #include <string> #include <sstream> #include <iostream> using namespace std; int main() { stringstream ss("this is a string\n"); string str(ss.str()); const char* cstr1 = str.c_str(); const std::string& resultstr = ss.str(); const char* cstr2 = resultstr.c_str(); cout << cstr1 // Prints correctly << cstr2; // No more error : cstr2 points to resultstr memory that is still alive as we used the const reference to keep it for a time. system("PAUSE"); return 0; } 

इस तरह आप लंबे समय तक स्ट्रिंग प्राप्त करते हैं।

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

  std::string resultstr = ss.str(); const char* cstr2 = resultstr.c_str(); 

बेहतर और सरल होगा