2010-10-22 17 views
6

स्ट्रिंग :: c_str() को इंगित करके पॉइंटर कहां लौटाता है? निम्नलिखित कोड स्निपेट में, मैंने सोचा कि मैं एक सेगमेंटेशन गलती दूंगा लेकिन यह मुझे सही आउटपुट देता है। यदि स्ट्रिंग :: c_str() बिंदु स्ट्रिंग ऑब्जेक्ट के अंदर एक आंतरिक स्थान पर लौटाता है, तो जब फ़ंक्शन लौटाता है और ऑब्जेक्ट विनाशक को बुलाया जाता है, तो मुझे एक अवैध स्मृति पहुंच मिलनी चाहिए।स्ट्रिंग :: c_str क्वेरी

#include <iostream> 
#include <string> 
using namespace std; 

const char* func() 
{ 
    string str("test"); 
    return str.c_str(); 
} 

int main() 
{ 
    const char* p = func(); 
    cout << p << endl; 
    return 0; 
} 

Output: test 
Compiler: g++ 4.3.3 
Platform: ubuntu 2.6.28-19 

उत्तर

13

कहाँ सूचक को string::c_str() बिंदु को फोन करके लौटे करता है?

यह स्मृति में कुछ जगहों को इंगित करता है जहां std::string की सामग्री वाली एक शून्य-समाप्त स्ट्रिंग स्थित है।

सूचक वैध जब तक std::string संशोधित या नष्ट कर दिया जाता है। यदि आप c_str() या data() को फिर से कॉल करते हैं तो यह संभावित रूप से अमान्य भी है।

असल में, आपकी सबसे सुरक्षित शर्त c_str() से प्राप्त सूचक को अगली बार अमान्य कर दिया जाता है जब आप std::string ऑब्जेक्ट पर कुछ करते हैं।

मैं गलत स्मृति पहुँच मिलना चाहिए।

नहीं, आप अपरिभाषित व्यवहार मिलता है। आपको किसी प्रकार की स्मृति एक्सेस त्रुटि मिल सकती है (जैसे सेगमेंटेशन गलती), लेकिन आपका प्रोग्राम भी सही ढंग से चलना जारी रख सकता है। यह एक बार काम करने लगता है जब आप अपना प्रोग्राम चलाते हैं लेकिन अगली विफल हो जाते हैं।

+0

AFAICT, सूचक 'c_str() द्वारा दिया (या अपने कार्यक्रम दुर्घटना या ब्रह्मांड को उड़ाने ...)' एक गैर स्थिरांक कार्य करने के लिए अगली कॉल तक मान्य है। चूंकि 'c_str()' और 'डेटा()' दोनों 'const' themelves हैं, इसलिए वे पहले लौटाए गए पॉइंटर्स को अमान्य नहीं कर सकते हैं। – MSalters

+1

@MSalters: मैं इतनी के रूप में अच्छी तरह से सोचा है, लेकिन: "संदर्भ, संकेत, और iterators एक' basic_string' अनुक्रम के तत्वों की चर्चा करते हुए कहा कि 'basic_string' वस्तु के निम्न उपयोगों द्वारा अवैध जा सकता है: ...' डेटा कॉलिंग () 'और' c_str() 'सदस्य कार्य "(सी ++ 03 21.3/5)। मैं 'c_str() 'को स्ट्रिंग में किसी तत्व को पॉइंटर लौटने के रूप में मानता हूं ताकि पॉइंटर _could_ को किसी अन्य कॉल द्वारा' c_str() 'में अमान्य कर दिया जा सके। मैं उस पर गलत हो सकता था। –

+0

मुझे लगता है कि यह विचार था कि basic_string c_str() को अपने आंतरिक बफर में '\ 0' जोड़कर और उस संलग्न बफर में पॉइंटर लौटकर लागू कर सकता है। ऐसा कार्यान्वयन शायद ही कभी '\ 0' स्टोर करेगा, और दो प्रतियों को कभी भी स्टोर नहीं करेगा।आपके द्वारा उद्धृत पाठ यह अनुमति देता है - यह निर्दिष्ट नहीं है कि 'c_str' उन तत्वों की प्रतिलिपि में तत्वों या पॉइंटर को पॉइंटर देता है या नहीं। – MSalters

2

आप इसे प्रिंट करने की क्या अपेक्षा करेंगे?

#include <iostream> 
#include <string> 

int main() 
{ 
    int* test = new int[20]; 
    test[15] = 5; 
    std::cout << test[15] << "\n"; 
    delete[] test; 
    std::cout << test[15] << "\n"; 
    return 0; 
} 

वी.एस. 2010 को जारी मोड में, मैं इस परिणाम मिलता है:

पुनः आवंटित की जाती स्मृति जब आप इसे तक पहुँचने का प्रयास जरूरी एक अपवाद फेंक नहीं है । मूल्य जरूरी नहीं है, या तो फिर से लिखा जाए। (दिलचस्प है, अगर मैं डिबग मोड में संकलन बदलता हूं, तो संकलक -572662307 के साथ मान को ओवरराइट करता है)।

जब आप इसे तक पहुँचने का प्रयास क्या होता है मानक से अपरिभाषित है। इसका मतलब है कि संकलक ऐसा कुछ भी कर सकता है जो ऐसा करने जैसा लगता है, या कुछ भी नहीं करना चुनता है।

+0

उत्कृष्ट चित्रण .... – Tanuj

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