2012-01-05 14 views
13

सी ++ 11 §12.1/14 का निर्माण:स्थिरांक वस्तु

एक स्थिरांक वस्तु के निर्माण के दौरान, अगर वस्तु या उसके subobjects के किसी भी मूल्य एक lvalue के माध्यम से पहुँचा है कि नहीं कन्स्ट्रक्टर के पॉइंटर से सीधे, अप्रत्यक्ष रूप से प्राप्त किया गया, इस प्रकार प्राप्त वस्तु या उपरोक्त का मूल्य निर्दिष्ट नहीं है। [उदाहरण:

struct C; 
void no_opt(C*); 

struct C { 
    int c; 
    C() : c(0) { no_opt(this); } 
}; 

const C cobj; 

void no_opt(C* cptr) { 
    // value of cobj.c is unspecified 
    int i = cobj.c * 100; 
    cptr->c = 1; 
    // value of cobj.c is unspecified 
    cout << cobj.c * 100 << '\n'; 
} 

ऊपर के उदाहरण संकलन 100 आउटपुट। मेरा सवाल यह है कि cobj.c का मान निर्दिष्ट क्यों किया जाना चाहिए जब प्रारंभिक सूची इसे कन्स्ट्रक्टर में प्रवेश करने से पहले 0 पर सेट करे? यदि गैर-कॉन्स्ट ऑब्जेक्ट का उपयोग किया जाता है तो यह व्यवहार अलग-अलग कैसे होता है?

+0

मुझे लगता है कि उपरोक्त उदाहरण में 'cobj।'cobj' पूरी तरह से निर्मित होने से पहले सी' का उपयोग किया जाता है। ऐसा लगता है कि गैर-कॉन्स ऑब्जेक्ट्स के लिए भी यह क्रिया संदिग्ध है। –

+0

@MatthieuM। क्यूं कर? मुझे मान्य लगता है (भले ही आप संरचना सी में बेस क्लास जोड़ते हैं)। –

+0

@VJovic: जब तक कि कन्स्ट्रक्टर नहीं चलता है, तब तक ऑब्जेक्ट ज़िंदा नहीं है - सटर के ले लेते हैं [कन्स्ट्रक्टर विफलताओं (या ऑब्जेक्ट्स जो कभी नहीं थे)] (http://www.gotw.ca/publications /mill13.htm)। यदि कोई वस्तु अभी तक जीवित नहीं है, तो इसका उपयोग संदिग्ध है। मैं नहीं कहता कि यह अनिवार्य रूप से अनिर्धारित या अनिर्दिष्ट है, बस यह "खराब गंध" करता है। –

उत्तर

6

वास्तव में const ऑब्जेक्ट्स को संकलक द्वारा वैध स्थिरांक के रूप में माना जा सकता है। यह मान सकता है कि उनके मूल्य कभी भी नहीं बदलते हैं या उन्हें const मेमोरी में भी स्टोर करते हैं, उदा। रॉम या फ्लैश। इसलिए, जब तक ऑब्जेक्ट वास्तव में स्थिर नहीं है, तब तक आपको this द्वारा प्रदत्त गैर-कॉन्स्ट एक्सेस पथ का उपयोग करने की आवश्यकता है। यह स्थिति केवल वस्तु निर्माण और विनाश के दौरान मौजूद है।

बेतकल्लुफ़, मुझे लगता है, क्योंकि वस्तु जीवन भर पहले से ही समाप्त हो गया है और cobj.c दुर्गम है जैसे ही cobj के लिए नाशक शुरू होता है वहाँ विनाशकर्ता के लिए एक इसी आवश्यकता होने की जरूरत नहीं है।

मैथ्यूयू का उल्लेख है, यह निर्माण या विनाश के दौरान this के माध्यम से किसी ऑब्जेक्ट तक पहुंचने के लिए एक मजबूत "कोड गंध" है। सी ++ 11 §3.8 [basic.life] ¶1 और 6 की समीक्षा, यह प्रतीत होता है कि cobj.c कन्स्ट्रक्टर के अंदर यूबी है क्योंकि यह विनाशक के अंदर है, चाहे वस्तु const या §12.1/14 हो, क्योंकि इसका जीवनकाल शुरू नहीं होता है जब तक कि प्रारंभिकता पूर्ण नहीं होती है (कन्स्ट्रक्टर रिटर्न)।

यह काम करने की संभावना हो सकती है, लेकिन यह अच्छे सी ++ प्रोग्रामर के लिए अलार्म रिंग करेगा, और पुस्तक द्वारा यह अवैध है।

+0

'सी(): सी (0) {सी = 1; } '- तो आप क्या कह रहे हैं कि यह भी मान्य नहीं है? –

+0

यह ऑफ-विषय लगता है: यह इस तथ्य को संबोधित नहीं करता है कि 'cobj.c' के पास' सी 'के कन्स्ट्रक्टर के चलते एक अनिर्दिष्ट मूल्य है (प्रारंभिक सूची की सूची के बाद भी)। यह भी पता नहीं लगाता कि एक कॉन्स और गैर-कॉन्स ऑब्जेक्ट्स के बीच व्यवहार अलग क्यों होगा (इस संबंध में)। –

+0

@MatthieuM। मुझे लगता है कि मैंने उन दोनों मुद्दों को कवर किया है। समस्या यह है कि संकलक 'cobj.c' पहुंच पथ को उस मान के रूप में पहचान सकता है जो परिवर्तित नहीं हो सकता है। कोई फर्क नहीं पड़ता कि कौन सा फ़ंक्शन इसे एक्सेस करता है, एक 'कॉन्स' ऑब्जेक्ट जिसमें निरंतर मान नहीं है, सीमा से बाहर है। – Potatoswatter

3

उद्धृत नियम का कारण संकलक को ऑब्जेक्ट की कॉन्स्ट-नेस के आधार पर अनुकूलन बनाने की अनुमति देना है। उदाहरण के लिए, अनुकूलन के आधार पर, आपका कंपाइलर i के साथ no_opt में दूसरे cobj.c * 100 को प्रतिस्थापित कर सकता है। अधिक संभावना है, इस विशेष मामले में, अनुकूलक i और इसके प्रारंभिक को पूरी तरह दबाएगा, इसलिए कोड काम पर दिखाई देगा। लेकिन यह केस नहीं हो सकता है यदि आप cptr->c को बदलने से पहले i आउटपुट भी करते हैं; यह सभी पर निर्भर करता है कि संकलक अनुकूलन को कैसे उत्तेजित करता है। लेकिन संकलक करने की अनुमति है मान लेते हैं कि *cptrcobj के लिए उपनाम नहीं है, क्योंकि cobj एक स्थिरांक वस्तु है, जहां आप *cptr के माध्यम से संशोधित रूप है, इसलिए यह अपरिभाषित व्यवहार के बिना एक स्थिरांक वस्तु को इंगित नहीं कर सकते।

यदि ऑब्जेक्ट नहीं है, तो मुद्दा यह नहीं होता है; कंपाइलर को हमेशा *cptr और cobj के बीच एक संभावित अलियासिंग को ध्यान में रखना चाहिए।

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