2014-09-25 4 views
5

पृष्ठभूमि: मैं एक बड़े कोड वातावरण में हूं जहां अपरिभाषित क्रम जिसमें वैश्विक रचनाकार चल रहे हैं समस्याग्रस्त है। तो मेरे पास एक कस्टम क्लास है जिसे पहली बार उपयोग तक प्रारंभ करने में देरी के लिए डिज़ाइन किया गया है। इसका सभी जादू इसके ऑपरेटर * और ऑपरेटर-> कार्यों के अंदर होता है; वे एकमात्र चीज परिभाषित हैं। यह स्वचालित-प्रारंभिक फ़ंक्शन पर उपलब्ध कराने के लिए, स्वयं के भीतर कुछ राज्य भी संग्रहीत करता है। निश्चित रूप से, राज्य को पीओडी होना चाहिए, ताकि पूरी कक्षा पीओडी हो, ताकि किसी के कोड चलने से पहले इसे पूरी तरह से स्थापित किया जा सके, ताकि हर जगह सभी कोड हर जगह सभी ग्लोबल्स का उपयोग कर सकें, बिना डर ​​के कि ग्लोबल्स ' अभी तक स्थापित नहीं किया गया है।सी ++ 11: क्या एक असाइनमेंट ऑपरेटर पीओडी होने से एक प्रकार को रोकता है, और इस प्रकार वैश्विक-आरंभिक होता है?

कुछ समय पहले किसी ने एक निजी, कभी-कभी परिभाषित असाइनमेंट ऑपरेटर जोड़ा, ताकि इस प्रकार को कभी भी असाइन नहीं किया जाएगा (इसे किसी भी तरह से बदलने के लिए डिज़ाइन नहीं किया गया है)। अब कोई और कह रहा है कि कक्षा टूट गई है क्योंकि यह पीओडी नहीं है। यदि इसके बजाय घोषित किया गया है लेकिन परिभाषित नहीं किया गया है, तो मैं इसे "= हटाएं" के रूप में घोषित करता हूं, मैं सोच रहा हूं कि यह किसी भी तरह बेहतर है। और वास्तव में, उस परिवर्तन के साथ, std :: is_pod <> :: मूल्य प्रकार के लिए सत्य देता है।

लेकिन क्या असाइनमेंट ऑपरेटर पीओडी होने से एक प्रकार को रोकता है? मैंने सोचा कि आवश्यकताएं सिर्फ इसलिए थीं कि इसमें केवल सार्वजनिक डेटा सदस्य, कोई वर्चुअल विधियां नहीं थीं, और कोई कन्स्ट्रक्टर या विनाशक नहीं था।

और मेरी स्थिति के लिए और अधिक बिंदु: क्या कभी-कभी परिभाषित असाइनमेंट ऑपरेटर की मौजूदगी वैश्विक स्तर पर सभी अन्य वैश्विक पीओडी के साथ वैश्विक प्रारंभिक समय पर कक्षा को शुरू करने में सक्षम होने से रोकती है?

घटित उदाहरण:

struct LazyString { 
    const char *c_str; 

    bool has_been_inited; 
    string *lazy_str_do_not_use_directly; 

    string &operator*() { return *get(); } 
    string *operator->() { return get(); } 

private: 
    string *get() { 
    // The real code uses a mutex, of course, to be thread-safe. 
    if (!has_been_inited) { 
     lazy_str_do_not_use_directly = new string(c_str); 
     has_been_inited = true; 
    } 
    return lazy_str_do_not_use_directly; 
    } 

    // Does this make the class non-POD? 
    // If so, does that mean that global variables of this type 
    // will not be initialized at global-initialization time, that wonderful 
    // moment in time where no code has yet been run? 
    void operator=(const LazyString&); 

    // If I do this instead, it breaks C++03 compatibility, but is this somehow better? 
    void operator=(const LazyString&) = delete; 
}; 

LazyString lazy = { "lazy" }; 

int main(int argc, char *argv[]) { 
    std::cout << *lazy; 
} 
+0

अपना खुद का ढेर मेमोरी प्रबंधन बनाना लगभग कोई अच्छा विचार नहीं है। आपको ऐसा क्यों लगता है कि आपको इसकी आवश्यकता है? (क्या आपका मतलब है [एसएच-ऑन-राइट] [http://stackoverflow.com/questions/12199710/legality-of-cow-stdstring-implementation-in-c11)) –

+1

आप भ्रमित पीओडी-नेस और स्थिर प्रारंभिकरण। न तो दूसरे पर निर्भर है। –

+0

चूंकि सभी डेटा सदस्य सार्वजनिक रूप से दिखाई दे रहे हैं, इसलिए घोषणा एक पीओडी बनाती है, हां। ** नोट: ** आप इस पीओडी प्रकार को प्रतिलिपि/असाइन करते समय, 'नई स्ट्रिंग (c_str);' अपने _lazy प्रारंभिक_ में 'अवांछित साइड इफेक्ट्स का अनुभव करेंगे। –

उत्तर

6

एक असाइनमेंट ऑपरेटर जा रहा पॉड

हाँ से एक प्रकार को रोकने करता है। एक पीओडी प्रकार त्रिभुज होना चाहिए; और इसलिए होना चाहिए जो तुलनीय रूप से कॉपी करने योग्य; और इसलिए कोई गैर-तुच्छ प्रतिलिपि या असाइनमेंट ऑपरेटर को स्थानांतरित नहीं करना चाहिए।

कोई भी उपयोगकर्ता द्वारा प्रदत्त ऑपरेटर गैर-तुच्छ है, इसलिए कॉपी कन्स्ट्रक्टर घोषित करने से वर्ग को गैर-तुच्छ बनाता है, और इसलिए गैर-पीओडी।

और इस प्रकार वैश्विक-आरंभिक हो रहा है?

नहीं। कोई भी तत्काल प्रकार, पीओडी या नहीं, वैश्विक चर हो सकता है।

अद्यतन:

यह हो सकता है स्थिर, बल्कि गतिशील रूप से, initialised: टिप्पणी से, आप से पूछना करने के लिए होती?

हां, क्योंकि इसमें एक छोटा कन्स्ट्रक्टर है; जब तक प्रारंभिक एक निरंतर अभिव्यक्ति है। आपके उदाहरण में, { "lazy" } एक निरंतर अभिव्यक्ति है, इसलिए LazyString को सांख्यिकीय रूप से प्रारंभ किया जा सकता है।

यहां महत्वपूर्ण विशेषता यह है कि इसमें एक छोटा सा कन्स्ट्रक्टर है, न कि यह पीओडी है। पीओडी का मतलब है कि यह प्रारंभिकरण के लिए प्रासंगिक नहीं, कई अन्य आवश्यकताओं को भी पूरा करता है।

+0

मुझे विश्वास है कि सही वाक्य "कोई भी उपयोगकर्ता - ** प्रदान किया गया ** ऑपरेटर गैर-तुच्छ है"। उदाहरण के लिए, 'कक्षा foo {foo और operator = (foo const &) = डिफ़ॉल्ट; }; 'एक मामूली उपयोगकर्ता द्वारा घोषित प्रति असाइनमेंट ऑपरेटर है। –

+0

@CassioNeri: सुधार के लिए धन्यवाद। अर्थ के इन रंगों का ट्रैक खोना आसान है। –

+0

आपने कहा "कोई भी तत्काल प्रकार, एक वैश्विक चर हो सकता है", और सच होने पर, यह मेरे प्रश्न का उत्तर नहीं देता है। उदाहरण के लिए, यदि मेरे पास foo1.cc है, जिसमें वैश्विक प्रारंभिक "int foo = printf (" हैलो वर्ल्ड \ n ");", और foo2 भी शामिल है।सीसी, जिसमें वैश्विक प्रारंभिक "बाहरी int foo; int bar = foo;" है, तो मुझे पता नहीं है, सी ++ मानक के अनुसार, कौन सा मान बार समाप्त हो जाएगा, क्योंकि दोनों गतिशील प्रारंभिक हैं। यही कारण है कि मैं किसी भी और सभी गतिशील प्रारंभिकताओं को खत्म करने की कोशिश कर रहा हूं ... लेकिन मुझे नहीं पता कि मैं इस संरचना के सभी क्षेत्रों को पीओडी के साथ निर्दिष्ट कर रहा हूं या नहीं। – jorgbrown

2

सी ++ में स्थिर भंडारण अवधि (इस श्रेणी में वैश्विक परिवर्तनीय गिरावट) के साथ गैर-स्थानीय चर के लिए प्रारंभिकरण के कई चरण हैं - भले ही प्रकार पीओडी है या नहीं।

  • शून्य आरंभीकरण किसी अन्य प्रारंभ
  • लगातार प्रारंभ लेता से पहले जगह लेता है
  • गतिशील प्रारंभ जगह

पहले दो आरंभीकरण के प्रकार गतिशील सक्रियण से पहले जगह ले जाना चाहिए। गतिशील प्रारंभिक स्थिति वह स्थिति है जहां प्रारंभिकरण का क्रम सेट करना मुश्किल हो सकता है। कुछ गतिशील प्रारंभिकरण अनियंत्रित है, कुछ को एक अनुवाद इकाई, आदि के भीतर आदेश दिया जाता है।

भले ही आप वैश्विक चर पीओडी नहीं हैं, आप सुनिश्चित कर सकते हैं कि किसी भी गतिशील init से पहले शून्य प्रारंभिक स्थान लिया जाएगा।

विवरण के लिए सी ++ 11 3.6.2 "गैर-स्थानीय चर का प्रारंभ" देखें।

+0

जैसा कि मैं इसे समझता हूं, गतिशील प्रारंभिक अन्य फ़ाइलों से ग्लोबल्स का संदर्भ दे सकता है। एक और फाइल के लेखक के रूप में, मैं यह सुनिश्चित करना चाहता हूं कि मेरे ग्लोबल सभी गतिशील प्रारंभिकरणों के लिए उपलब्ध हैं। यही है, मैं यह सुनिश्चित करना चाहता हूं कि मेरी कक्षा निरंतर प्रारंभिक समय पर शुरू हो। मुझे पता है कि अगर मेरी कक्षा पीओडी थी, या घोषित कॉन्सएक्सप्रस था, तो यह "निरंतर प्रारंभिक चरण" चरण के दौरान आरंभ होने की गारंटी होगी। लेकिन क्या मेरी LazyString कक्षा गतिशील init से पहले चलाने की गारंटी है? – jorgbrown

+0

कार्यक्रम में किसी गतिशील प्रारंभिकरण से पहले स्टेटिक प्रारंभिकता होती है। इसलिए आपकी 'LazyString' वैश्विक ऑब्जेक्ट को किसी भी अन्य ऑब्जेक्ट के गतिशील प्रारंभिकरण से पहले प्रारंभ किया जा सकता है 'LazyString :: get() '। –

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