2015-06-05 4 views
6

clang++ कभी भी default initialization of a const variable of class-type without a user-defined constructor की अनुमति नहीं देता है; g++ थोड़ा कम प्रतिबंधक है (नीचे देखें)। this answer के अनुसार, ऐसा इसलिए है क्योंकि पीओडी प्रकार "डिफ़ॉल्ट रूप से प्रारंभ नहीं होते हैं।" अगर मैं सही ढंग से समझता हूं, तो इसका मतलब है कि डिफ़ॉल्ट-प्रारंभिक डिफ़ॉल्ट-कन्स्ट्रक्टर का आह्वान नहीं करता है, न ही यह मूल्य-प्रारंभिकता का आह्वान करता है, इसलिए पीओडी प्रकार के अंदर डेटा सदस्यों को प्रारंभ नहीं किया जाता है। निस्संदेह इसमें कोई प्रारंभिक मान वाले कॉन्स पीओडी प्रकार का कोई अर्थ नहीं है, क्योंकि वे कभी भी प्रारंभ नहीं कर सकते हैं और इसलिए उपयोग करने के लिए सुरक्षित नहीं हैं।डिफ़ॉल्ट और कब डिफ़ॉल्ट रूप से एक कॉन्स वैरिएबल प्रारंभ करें?

इस स्थिति के कुछ वेरिएंट हैं:

  1. प्रकार तकनीकी रूप से है "पॉड", लेकिन कोई डेटा सदस्य (केवल कार्य करता है) शामिल हैं। (clang++ एक विशेष मामले के रूप में इस का इलाज नहीं है, और न ही, मुझे लगता है, मानक है, लेकिन g++ यह अनुमति नहीं है, भले ही निर्माता explicit चिह्नित है।)
  2. एक खाली निर्माता परिभाषित किया गया है {} का उपयोग कर। (यह समस्या का वर्णन करने वाले clang पृष्ठ पर अनुशंसित कार्यवाही है।)
  3. डिफ़ॉल्ट कन्स्ट्रक्टर =default घोषित किया गया है। (सी ++ 11 आगे; प्रकार को अभी भी पीओडी माना जाता है, इसलिए न तो कंपाइलर और न ही मानक इसे एक विशेष मामले के रूप में मानते हैं।)
  4. कुल प्रारंभिक रूप से {} का उपयोग करके स्पष्ट रूप से उपयोग किया जाता है, जो (यदि मैं सही ढंग से समझता हूं) मूल्य-प्रारंभिक बन जाता है । (सी ++ 11 आगे;। दोनों compilers और, मुझे लगता है, इस मानक-अनुमति देते हैं)

पहले मामले में, वहाँ कोई अप्रारंभीकृत सदस्य हो सकता है, इसलिए यह स्पष्ट नहीं है क्यों की किसी भी इन्स्टेन्शियशन क्लास को कभी भी "अनियमित" माना जाएगा, भले ही यह const है या नहीं। चूंकि g++ इस व्यवहार की अनुमति देता है, क्या यह उपयोग करने के लिए सुरक्षित है? यह clang++ और मानक द्वारा क्यों प्रतिबंधित है?

दूसरे और तीसरे मामलों में, का उपयोग कर =default के बजाय {} मेरे लिए अजीब लगता है की आवश्यकता (और वहाँ किसी भी अन्य मामलों में जहां g++ की अनुमति देता है पॉड-default-प्रारंभ जहां clang++ नहीं कर रहे हैं?)। संपादित करें:this question अंतर को काफी अच्छी तरह से बताता है, इसलिए मैंने इस भेद के बारे में पूछने वाले प्रश्न का हिस्सा हटा दिया है। (मैं अभी भी लगता है कि यह भाषा का एक बहुत भ्रामक पहलू है, हालांकि।)

अंत में, Foo f{} हमेशा शून्य प्रारंभ हो जाएगा की {}, =default, या परोक्ष-घोषित निर्मित प्रकार यदि Foo::Foo(void) है सदस्यों?

+0

क्या कोई सदस्य चर के साथ एक कॉन्स पीओडी प्रकार के लिए उपयोग-मामला है? आप गैर-कॉन्स एक का भी उपयोग कर सकते हैं, क्योंकि ऐसे कोई सदस्य नहीं हैं जिन्हें गलती से बदला जा सके। –

+0

@MattMcNabb मुझे यकीन नहीं है। यह एक ऐसा पैटर्न है जो एक सहयोगी के कोड में बार-बार पुनरावृत्ति करता है, टेम्पलेट कारखाने के कार्यों में (या ... ऐसा कुछ)। मैं कल सहयोगी से पूछने के लिए याद रखने की कोशिश करूंगा कि इरादा क्या है। –

+0

'{}' के साथ परिभाषित एक कन्स्ट्रक्टर एक छोटा कन्स्ट्रक्टर नहीं है। – 0x499602D2

उत्तर

5

चूंकि g ++ इस व्यवहार की अनुमति देता है, तो क्या इसका उपयोग सुरक्षित है?

किस अर्थ में सुरक्षित है? यह स्पष्ट रूप से पोर्टेबल नहीं है। हालांकि, यह आपको g ++ पर अप्रत्याशित परिणाम नहीं दे रहा है।

यह क्लैंग ++ और मानक द्वारा क्यों प्रतिबंधित है?

मुमकिन समिति या तो इसके बारे में नहीं सोचा था कि जब वे "उपयोगकर्ता द्वारा प्रदान की निर्माता की आवश्यकता" सी ++ 98 में नियम शब्दों में कहें, या फैसला किया है कि विशेष आवरण खाली पॉड कक्षाएं विनिर्देश जटिलता के लायक नहीं है ; clang ++ मानक का पालन कर रहा है। हालांकि, मानक likely going to change अधिक आम तौर पर आपको const Foo f; लिखने की अनुमति देता है जब तक कि निर्माता, वास्तव में, प्रत्येक सबोबजेक्ट को प्रारंभ नहीं करेगा।

अंत में, Foo f{}; हमेशा शून्य प्रारंभ हो जाएगा की निर्मित प्रकार यदि Foo::Foo(void){}, =default, या परोक्ष-घोषित किया जाता है के सदस्यों?

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

+0

मुझे "अप्रत्याशित परिणाम" अर्थ में वास्तव में "सुरक्षित" का मतलब था। एक बार फिर, अच्छा खुला मानक लिंक; आप उन्हें इतनी जल्दी कैसे पाते हैं (या बिल्कुल)? साथ ही, जब आप कहते हैं कि "मान-प्रारंभिक डिफ़ॉल्ट डिफॉल्ट कन्स्ट्रक्टर को कॉल करने से पहले शून्य-प्रारंभिकता नहीं करता है," क्या आपका मतलब है कि शून्य-प्रारंभिकता सभी आवश्यक नहीं होगी *? तो '= default' से' {} 'में बदलना वास्तव में * अनुचित-प्रारंभिक बग परिचय * कर सकता है? –

+0

@KyleStrand 1) इस विशेष जी ++/क्लैंग ++ अंतर से पहले एसओ पर पूछा गया है, इसलिए मुझे पता है कि इस पर एक खुला कोर मुद्दा है :) 2) हां, यह होने की गारंटी नहीं है, हालांकि कार्यान्वयन स्मृति को रोक सकता है हालांकि यह पसंद करता है (क्योंकि कोई अच्छी तरह से परिभाषित कार्यक्रम इसे देख सकता है)। तकनीकी रूप से बोलते हुए, यह अनिश्चित है, और इसे पढ़ने से यूबी (मॉड्यूलो 'हस्ताक्षरित चार' के लिए कुछ अपवाद) का कारण बनता है; 3) हां। –

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