2012-12-13 11 views
98

यदि मेरे पास फ़ंक्शन के अंदर एक चर है (कहें, एक बड़ी सरणी), तो क्या यह static और constexpr दोनों को घोषित करने के लिए समझ में आता है? constexpr गारंटी देता है कि सरणी संकलन समय पर बनाई गई है, तो static बेकार हो जाएगा?क्या स्थिर constexpr चर समझ में आता है?

void f() { 
    static constexpr int x [] = { 
     // a few thousand elements 
    }; 
    // do something with the array 
} 

static वास्तव में उत्पन्न कोड या अर्थ विज्ञान के मामले में क्या कर रही है?

+11

'constexpr' किसी भी समय संकलन समय की गारंटी नहीं देता है, संकलक रनटाइम पर 'constexpr' सामान का मूल्यांकन करने के लिए स्वतंत्र है। इसे संकलित समय पर कुछ मूल्यांकन करने के लिए मजबूर किया जाता है यदि आप उस संदर्भ में कुछ ऐसा करते हैं जहां संकलन समय पर जाना आवश्यक है। – Praetorian

+0

मेरा मानना ​​है कि @Praetorian सही है, और 'स्थैतिक' गारंटी नहीं देगा कि यह संकलन समय पर है, लेकिन यह केवल संकलन समय स्थिरांक के साथ संग्रहीत है। मुझे लगता है कि 'स्थिर' के बिना यह _theoretically_ समारोह के प्रत्येक आमंत्रण पर ढेर पर (विशाल) सरणी को धक्का देने के अनुरूप होगा। –

+3

@AndrewLazarus, न केवल सैद्धांतिक रूप से प्रत्येक आमंत्रण पर सरणी को ढेर पर धक्का देने के लिए अनुरूप है, यह सैद्धांतिक रूप से आवश्यक है (जैसा कि नियम के रूप में मॉड्यूल है)। अभ्यास में, मेरे अनुभव में, यह हमेशा अच्छा होता है। अधिक जानकारी के लिए मेरा जवाब देखें। – rici

उत्तर

120

संक्षिप्त उत्तर यह है कि न केवल static उपयोगी है, यह हमेशा वांछित होने वाला है।

सबसे पहले, ध्यान दें कि static और constexpr एक दूसरे से पूरी तरह से स्वतंत्र हैं। static निष्पादन के दौरान वस्तु के जीवनकाल को परिभाषित करता है; constexpr निर्दिष्ट करता है कि ऑब्जेक्ट संकलन के दौरान उपलब्ध होना चाहिए। संकलन और निष्पादन समय और स्थान दोनों में विघटन और असंतुलित हैं। तो एक बार प्रोग्राम संकलित हो जाने पर, constexpr अब प्रासंगिक नहीं है।

हर चर घोषित constexpr परोक्ष const लेकिन const और static लगभग ओर्थोगोनल (static const पूर्णांकों के साथ बातचीत के लिए छोड़कर।)

C++ ऑब्जेक्ट मॉडल (§ 1.9) की आवश्यकता है कि थोड़ा-क्षेत्रों के अलावा अन्य सभी वस्तुओं पर कब्जा स्मृति की कम से कम एक बाइट और पते हैं; इसके अलावा किसी दिए गए पल में किसी कार्यक्रम में देखने योग्य ऐसी सभी वस्तुओं के अलग-अलग पते (अनुच्छेद 6) होना चाहिए। इसने संकलक को स्थानीय गैर स्थैतिक कॉन्स सरणी के साथ किसी फ़ंक्शन के प्रत्येक आमंत्रण के लिए स्टैक पर एक नई सरणी बनाने की आवश्यकता नहीं है, क्योंकि संकलक as-if सिद्धांत में शरण ले सकता है बशर्ते यह साबित हो सके कि ऐसा कोई अन्य वस्तु नहीं कर सकता परीक्षण में रहना।

यही साबित करने के लिए आसान नहीं हो रहा है, दुर्भाग्य से, जब तक कि समारोह तुच्छ है (उदाहरण के लिए, यह किसी भी अन्य समारोह जिसका शरीर अनुवाद इकाई के भीतर दिखाई नहीं देता है फोन नहीं करता है) क्योंकि सरणियों, कम या ज्यादा परिभाषा के द्वारा, पते हैं तो ज्यादातर मामलों में, गैर-स्थैतिक const(expr) सरणी को प्रत्येक आमंत्रण पर ढेर पर पुनर्निर्मित करना होगा, जो संकलन समय पर गणना करने में सक्षम होने के बिंदु को हरा देता है।

दूसरी तरफ, स्थानीय static const ऑब्जेक्ट सभी पर्यवेक्षकों द्वारा साझा किया जाता है, और इसके अलावा इसे प्रारंभ किया जा सकता है भले ही इसे परिभाषित किया गया कार्य कभी भी नहीं कहा जाता है। इसलिए उपरोक्त में से कोई भी लागू नहीं होता है, और एक कंपाइलर न केवल इसके केवल एक उदाहरण उत्पन्न करने के लिए स्वतंत्र है; यह केवल पढ़ने के लिए भंडारण में इसका एक उदाहरण उत्पन्न करने के लिए स्वतंत्र है।

तो आपको निश्चित रूप से static constexpr का उपयोग अपने उदाहरण में करना चाहिए।

हालांकि, एक ऐसा मामला है जहां आप static constexper का उपयोग नहीं करना चाहते हैं। जब तक constexpr घोषित ऑब्जेक्ट या तो ODR-used या घोषित static है, तो संकलक इसे शामिल करने के लिए स्वतंत्र नहीं है। यह बहुत उपयोगी है, क्योंकि यह अनावश्यक बाइट्स के साथ संकलित प्रोग्राम को प्रदूषित किए बिना संकलन-समय अस्थायी constexpr सरणी के उपयोग की अनुमति देता है। उस स्थिति में, आप static का उपयोग नहीं करना चाहते हैं, क्योंकि static ऑब्जेक्ट को रनटाइम पर मौजूद होने की संभावना है।

+1

जब मैंने टिप्पणी की तो मैं इस बारे में सोच रहा था। आईएसटीएम 'कॉन्स्टेक्सप्र', 'कॉन्स्टेक्स' के विपरीत, हमेशा पढ़ने-योग्य भंडारण में रखा जा सकता है (आप 'कॉन्स्टेक्सप्र' को दूर नहीं कर सकते हैं [?]) और इससे ढेर पर ताजा प्रतिलिपि बनाने की आवश्यकता को रोक दिया जाएगा, भले ही यह 'const' चर के लिए आवश्यक होगा। पूलिंग निरंतर शाब्दिक तारों की तरह क्रमबद्ध करें। लेकिन मुझे नहीं पता कि यह कानूनी है या नहीं। –

+1

@ एंड्रयूलाज़ारस, आप 'कॉन्स' ऑब्जेक्ट से 'कॉन्स्ट' को नहीं हटा सकते हैं, केवल 'कॉन्स एक्स *' से जो 'एक्स' को इंगित करता है। लेकिन यह बात नहीं है; मुद्दा यह है कि स्वचालित वस्तुओं में स्थिर पते नहीं हो सकते हैं। जैसा कि मैंने कहा था, संकलन समाप्त हो जाने के बाद 'कॉन्स्टेक्सप्र' का अर्थ सार्थक हो जाता है, इसलिए दूर करने के लिए कुछ भी नहीं है (और संभवतः कुछ भी नहीं, क्योंकि वस्तु को रनटाइम पर मौजूद होने की भी गारंटी नहीं है।) – rici

+0

सी ++ में 1y, contexpr कार्यों का गठन नहीं किया जाएगा। – refi64

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