2012-02-04 15 views
20

क्या इस कोड के साथ गलत है, कारण है कि मैं गलत जवाब मिलता है:सी ++ निर्माता: कचरा जबकि स्थिरांक संदर्भ का आरंभीकरण

class X 
{ 
private: 
     const int a; 
     const int& b; 
public: 
     X(): a(10) , b(20) 
     { 
     //  std::cout << "constructor : a " << a << std::endl; 
     //  std::cout << "constructor : b " << b << std::endl; 
     } 

     void display() 
     { 
      std::cout << "display():a:" << a << std::endl; 
      std::cout << "display():b:" << b << std::endl; 

     } 
}; 


int 
main(void) 
{ 
     X x; 
     x.display(); 
return 0; 
} 

ऊपर कोड मुझे परिणाम दे देंगे के रूप में

display():a:10 
display():b:1104441332 

लेकिन यदि मैं डिफ़ॉल्ट कन्स्ट्रक्टर के अंदर 2 लाइनों को टिप्पणी करता हूं तो यह मुझे उचित परिणाम देता है जो

constructor : a 10 
constructor : b 20 
display():a:10 
display():b:20 

कृपया मदद करें, धन्यवाद

उत्तर

24

आप को अस्थायी के संदर्भ के रूप में प्रारंभ कर रहे हैं।

मूल्य 20 बनाया गया है और केवल निर्माता के दायरे के लिए मौजूद है।

इसके बाद कोड का व्यवहार बहुत दिलचस्प है - मेरी मशीन पर, मुझे आपके द्वारा पोस्ट किए गए लोगों से अलग-अलग मान मिलते हैं, लेकिन मौलिक व्यवहार अभी भी नोडेटर्मिनिस्टिक है।

ऐसा इसलिए है क्योंकि जब संदर्भ बिंदुओं के दायरे से बाहर निकलता है, तो यह अप्रत्याशित व्यवहार देने के बजाय कचरा स्मृति का संदर्भ देना शुरू करता है।

Does a const reference prolong the life of a temporary? देखें; जवाब सी ++ मानक के प्रासंगिक अनुभाग को https://stackoverflow.com/a/2784304/383402 लिंक, विशेष रूप से नीचे पाठ:

A temporary bound to a reference member in a constructor’s ctor-initializer 
(12.6.2) persists until the constructor exits. 

इस के बाद क्यों तुम हमेशा निर्माता के भीतर प्रिंट में सही मूल्य मिलता है, और शायद ही कभी होता है (लेकिन संभवतः कभी कभी!) । जब निर्माता बाहर निकलता है, तो संदर्भ लटकता है और सभी दांव बंद होते हैं।

+0

आपके उत्तर के लिए धन्यवाद। जो परिणाम बताता है। लेकिन क्या मुझे पता चलेगा कि बी को कैसे शुरू किया जाए? –

+1

@ विवेकबास्पा: क्या यह कुछ वैरिएबल का संदर्भ देता है, जैसा कि आप चाहते हैं। या, बस इसे 'ए' जैसे मान बनाएं। –

+1

@ विवेकबास्पा यह एक 'int' है, इसलिए आप शायद यह किसी भी तरह से संदर्भ नहीं चाहते हैं। 'int' की प्रतिलिपि बनाने की तरह स्नॉट महंगा है। – Borealid

4

b एक अस्थायी को संदर्भित करता है। अस्थायी 20 अस्थायी रूप से दायरे से बाहर हो गया है, जो आपने पढ़ा है (जब मुद्रण) एक अमान्य स्थान है जब तक यह पढ़ा जाता है।

असंगत परिणामों की व्याख्या करने के लिए:

यह अपरिभाषित व्यवहार है। एक और वास्तुकला के लिए

  • परिवर्तन आपके संकलक
  • परिवर्तन आपके संकलक सेटिंग्स
  • निर्माण
  • परिवर्तन आपके क्लास 'सदस्य लेआउट
  • जोड़ने या से बातें निकालें: क्या आप देख विभिन्न अगर तुम हो सकता है x
  • आदि के कहने के पास स्मृति क्षेत्र

आपको हमेशा अनिर्धारित व्यवहार से बचना चाहिए।

लेकिन मूल्य क्यों बदल जाएगा? आपका संदर्भ संभवतः एक स्टैक पते को संदर्भित करता है जिसे मुद्रित किए जाने तक पुनः लिखा गया है (उदा। पुन: उपयोग किया गया)।

+0

मैं ईमानदारी से अंतिम का अर्थ नहीं बना सकता "क्योंकि यह अलग क्यों है ..." भाग। मैं इसकी सराहना करता हूं अगर आप यह बता सकते हैं कि आप किस बारे में बात कर रहे हैं। यहां तक ​​कि पहले "क्यों के लिए:" यह सब स्पष्ट नहीं है, हालांकि ':' के बाद क्या होता है, यह समझ में आता है। – batbrat

+0

@batbrat विस्तारित – justin

+1

+1 अच्छा काम! यह अब इतना बेहतर समझ में आता है। – batbrat

3

आप const& को अस्थायी रूप से बाध्य कर रहे हैं, जो कि कन्स्ट्रक्टर को कॉल से परे नहीं रहता है। सी ++ 03 मानक specfically कहते हैं "एक कन्स्ट्रक्टर के सीटीओ-प्रारंभकर्ता (12.6.2) में एक संदर्भ सदस्य के लिए एक अस्थायी बाध्य जब तक कि निर्माता बाहर निकलता है" (12.2/5 "अस्थायी वस्तुओं")।

तो आपके कोड में अपरिभाषित व्यवहार है - आपको बकवास हो सकता है, या ऐसा कुछ जो 'काम' लगता है।

Fwiw, MSVC 2010 कोड पर निम्न चेतावनी देता है:

C:\temp\test.cpp(12) : warning C4413: 'X::b' : reference member is initialized to a temporary that doesn't persist after the constructor exits 
19

मैं दूँगा मेरी संकलक जवाब यह एक:

$ g++ -std=c++98 -Wall -Wextra -pedantic test.cpp 
test.cpp: In constructor 'X::X()': 
test.cpp:9:26: warning: a temporary bound to 'X::b' only persists until the constructor exits [-Wextra] 
$ 

आप के रूप में अपने संकलक पर चेतावनी चालू करना चाहिए कुंआ।

+0

उत्तर के लिए धन्यवाद, क्या आप मुझे समझा सकते हैं कि बी एक अस्थायी प्रारंभिक क्यों है? मैं प्रारंभिक सूची –

+1

@ विवेकबास्पा के माध्यम से कॉन्स वैल्यू शुरू करने की कोशिश कर रहा हूं: 'एक्स :: बी' एक कॉन्स वैल्यू है, न कि कॉन्स वैल्यू। –

+1

@ विवेकबासप्पा 'कॉन्स्ट' समस्या नहीं है, समस्या यह है कि यह एक * संदर्भ * है जिसका संदर्भ देने के लिए कुछ भी नहीं है। –

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