2016-07-25 10 views
6

मैं थोड़ा निम्नलिखित सी ++ कोड के बारे में उलझन में हूँ:प्रारंभ

#include <iostream> 

using namespace std; 

void test(const string& str) 
{ 
    static const char * const c = str.c_str(); 
    cout << c << endl; 
} 

int main(int argc, char* argv[]) 
{ 
    test("Hello"); 
    test("Nooo"); 
    return 0; 
} 

चर c के बाद से static और const के रूप में घोषित किया जाता है, नहीं यह केवल एक बार प्रारंभ किया जाना चाहिए और अपनी प्रारंभिक मूल्य रखने प्रक्रिया पूरी होने तक? इस तर्क के अनुसार, मैं निम्नलिखित उत्पादन उम्मीद कर रहा था:

Hello 
Hello 

लेकिन मुझे मिल गया:

Hello 
Nooo 

आप स्पष्ट कर सकते हैं क्यों चर c का मूल्य दो समारोह के बीच संशोधित किया गया है यहां तक ​​कि इसे हालांकि कॉल const चर है?

उत्तर

14

आपके प्रोग्राम में अपरिभाषित व्यवहार है।

जब आप test को "hello" पास, एक अस्थायी std::string वस्तु बनाई गई है, और कहा कि स्ट्रिंग c से निर्माण किया है (जो स्ट्रिंग वस्तु के डेटा के लिए सिर्फ एक सूचक है)।

जब फ़ंक्शन कॉल समाप्त होता है, तो अस्थायी std::string ऑब्जेक्ट नष्ट हो जाता है, और c एक खतरनाक सूचक बन जाता है। इसका उपयोग फिर से अपरिभाषित व्यवहार है।

आपके मामले में, दूसरा अस्थायी std::string वस्तु के डेटा पहले एक है, इसलिए c अंक है कि डेटा के रूप में ठीक उसी स्मृति पता है। यह गारंटी नहीं है।

+0

दरअसल यह अनिर्धारित नहीं है। ** Dereferencing ** यह अपरिभाषित है। चूंकि इसे संदर्भित करते समय हमेशा एक वैध पता होता है, यह एक वैध प्रोग्राम है। – StoryTeller

+3

@StoryTeller, 'cout << c << endl;' सूचक को अस्वीकार करता है। –

+1

@StoryTeller आउटपुट ऑपरेटर dereferencing का उपयोग करता है। –

1

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

यह संभव है कि मेमोरी मैनेजर एक ही मेमोरी क्षेत्र का पुन: उपयोग करे, ताकि आप अपने परिणामों में हैलो और नोउ देखें।

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