2009-04-07 2 views
9

क्या आरंभकर्ता सूची हमेशा कन्स्ट्रक्टर कोड से पहले संसाधित की जाएगी?क्या आरंभकर्ता सूची हमेशा कन्स्ट्रक्टर कोड से पहले संसाधित की जाएगी?

दूसरे शब्दों में, निम्न कोड हमेशा <unknown> प्रिंट होगा, और निर्माण वर्ग "के नाम से" होगा source_ का मान (यदि वैश्विक चर something है true)?

class Foo { 
    std::string source_; 
public: 
    Foo() : source_("<unknown>") { 
    std::cout << source_ << std::endl; 
    if(something){ 
     source_ = "known"; 
    } 
    } 
}; 

उत्तर

12

हाँ, कहीं भी होगी, प्रति C++11: 12.6.2 के रूप में।

इनिट-सूचियों का उपयोग करने का मुख्य कारण संकलक के साथ संकलक की सहायता करना है। गैर-मूल प्रकारों के लिए इनिट-सूचियां (यानी, int, float इत्यादि के बजाय कक्षा वस्तुओं) आमतौर पर जगह बनाई जा सकती हैं।

यदि आप ऑब्जेक्ट बनाते हैं तो इसे कन्स्ट्रक्टर में असाइन करें, यह आमतौर पर अस्थायी वस्तुओं के निर्माण और विनाश में परिणाम होता है, जो अक्षम है।

इनिट-सूचियां इस से बच सकती हैं (यदि संकलक इसके ऊपर है, तो निश्चित रूप से उनमें से अधिकांश होना चाहिए)।

निम्नलिखित पूर्ण प्रोग्राम 7 आउटपुट करेगा, लेकिन यह एक विशिष्ट कंपाइलर (साइगविन जी ++) के लिए है, इसलिए यह मूल प्रश्न में नमूना से कहीं अधिक व्यवहार की गारंटी नहीं देता है।

हालांकि, ऊपर दिए गए पहले पैराग्राफ में उद्धरण के अनुसार, मानक वास्तव में इसकी गारंटी देता है।

#include <iostream> 
class Foo { 
    int x; 
    public: 
     Foo(): x(7) { 
      std::cout << x << std::endl; 
     } 
}; 
int main (void) { 
    Foo foo; 
    return 0; 
} 
+0

मुझे आश्चर्य है कि क्यों लोग पहले स्रोत को संकलित करने की कोशिश नहीं करते हैं :) – arul

+1

@arul: @dehmann केवल एक संकलक हो सकता है। यदि वह व्यवहार कार्यान्वयन-परिभाषित है, तो संकलन मदद नहीं करेगा। आपको मानक को संदर्भित करना होगा। – paxdiablo

+1

हां, बस संकलन और कोशिश कर रहा है आपको यह नहीं बताता कि क्या यह हर जगह काम करेगा। – Frank

7

हाँ, सी ++ constructur कोड कॉल करने से पहले सभी सदस्यों निर्माण करती है।

7

जैसा कि पहले से ही उत्तर दिया गया है, प्रारंभिक सूचियां से पहले कन्स्ट्रक्टर ब्लॉक में प्रवेश करती हैं। तो यह कन्स्ट्रक्टर बॉडी में उपयोग (प्रारंभिक) सदस्यों का उपयोग करने के लिए पूरी तरह से सुरक्षित है।

आप के लिए होने के बारे में स्वीकार किए जाते हैं जवाब में एक टिप्पणी की है निर्माता तर्क का उल्लेख है, लेकिन नहीं सदस्य निर्माता ब्लॉक के अंदर वार्स। आप नहीं करते

यह है कि आप इस तथ्य है कि आप मानकों के लिए नहीं सदस्य को देखें और चाहिए समझ लिया विशेषताओं प्रारंभ सूची के अंदर संभव है। उदाहरण के लिए, एक दसवीं कक्षा दो सदस्य हैं कि दिए गए (a_ और b_) प्रकार int की है, तो निम्न निर्माता ख़राब ढंग से परिभाषित किया जा सकता है:

X::X(int a) : a_(a), b(a_*2) {} 

संभावित समस्या यहाँ है कि में तत्वों के निर्माण प्रारंभिक सूची कक्षा में घोषणा के आदेश पर निर्भर करती है, न कि जिस क्रम में आप प्रारंभिक सूची टाइप करते हैं। यदि वर्ग के रूप में परिभाषित किया गया:

class X 
{ 
public: 
    X(int a); 
private: 
    int b_; 
    int a_; 
}; 

उसके बाद, आप कैसे में प्रारंभ सूची टाइप की परवाह किए बिना, तथ्य यह है कि b_ (a_ * 2) निष्पादित किया जाएगा से पहले a_ की घोषणा के बाद से आरंभ नहीं हो जाता है सदस्य पहले बी_ और बाद में ए_ है। इससे एक बग बन जाएगा क्योंकि आपका कोड बी (बी पर निर्भर करता है) बी_ पर ए_ के मान से दोगुना होता है, और वास्तव में बी_ में कचरा होता है।सरल समाधान के सदस्यों की बात कर रहा है:

X::X(int a) : a_(a), b(a*2) {} // correct regardless of how X is declared 

इस चूक से बचना कारण है कि आप सदस्य अन्य सदस्यों के प्रारंभ के हिस्से के रूप विशेषताओं का उपयोग करने के लिए नहीं सुझाव दिया जाता है।

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