2010-03-03 12 views
6

मैं लंबे समय तक अनुपस्थिति के बाद सी ++ पर लौट रहा हूं और मैं काफी अच्छी तरह से ज्ञात स्थिर प्रारंभिक समस्या की मेरी समझ पर थोड़ा सा ठोकर खा रहा हूं।सी ++ स्थिर कॉन्स और प्रारंभिकरण (क्या कोई फियास्को है)

चलो कहते हैं कि नीचे दिए गए के रूप में (ध्यान दें कि मुझे पता है कि x और y getters और setters के साथ निजी होना चाहिए हूँ, ये सिर्फ संक्षिप्तता के लिए छोड़ दिए गए हैं) मैं एक साधारण वर्ग Vector2 करते हैं:

class Vector2 { 

public: 
    Vector2(float x, float y) :x(x), y(y) {}; 
    float x,y; 
} 

अब , यदि मैं x और y के साथ एक वेक्टर 2 का प्रतिनिधित्व करने के लिए स्थिर स्थिरांक सदस्य निर्दिष्ट करना चाहता हूं, तो मैं आगे बढ़ने के बारे में अनिश्चित हूं - स्थिर स्थिर सदस्य स्थिर प्रारंभिक समस्या का असफल हो जाएंगे या उन्हें ठोस बनाने का कार्य करेंगे वे ठीक हैं? मैं निम्नलिखित संभावनाओं के साथ कर रही हूँ:

संभावना 1:

// .h 
class Vector2 { 

public: 
    Vector2(float x, float y) :x(x), y(y) {} 
    static const Vector2 ONE; 
    float x,y; 
}; 

// .cpp 
const Vector2 Vector2::ONE = Vector2(1.f, 1.f); 

संभावना 2:

// .h 
class Vector2 { 

public: 
    Vector2(float x, float y) :x(x), y(y) {} 
    static const Vector2& getOne(); 
    float x,y; 
private: 
    static const Vector2 ONE; 
}; 

// .cpp 
const Vector2 Vector2::ONE = Vector2(1.f, 1.f); 

static const Vector2& Vector2::getOne() { 
    return ONE; 
} 

संभावना 3:

// .h 
class Vector2 { 

public: 
    Vector2(float x, float y) :x(x), y(y) {} 
    static const Vector2& getOne(); 
    float x,y; 
}; 

// .cpp 
const Vector2& Vector2::getOne() { 
    static Vector2 one(1.f,1.f); 
    return one; 
} 

अब, मेरी पसंदीदा तरीका यह लिखने के लिए संभावना 2 के रूप में होगा, सिर्फ इसलिए कि यह मेरे लिए एक अधिक आरामदायक वाक्यविन्यास है। हालांकि, अगर मैं किसी अन्य वर्ग में getOne() विधि को किसी अन्य स्थिर विधि से कॉल करता हूं तो क्या मुझे क्रैशिंग और जलने का खतरा होता है? जैसा कि मैंने कहा, ऐसा इसलिए है क्योंकि मैं एक सादे स्थिर की बजाय स्थिर स्थिरता का उपयोग कर रहा हूं कि मैं इस सवाल से पूछ रहा हूं क्योंकि मुझे सादे स्थैतिक वर्ग के सदस्य मुद्दों पर बहुत कुछ मिला है, लेकिन स्थिर मुद्दों पर कुछ भी नहीं है।

मुझे संदेह है कि मुझे इस तथ्य से कुछ भी नहीं मिला है कि मैं स्थैतिक आधार का उपयोग कर रहा हूं और सुरक्षित होने के लिए संभावना 3 के साथ जाने की आवश्यकता होगी, लेकिन मैं सिर्फ यह पूछना चाहता हूं कि कोई मेरे लिए इस पर कुछ प्रकाश डाल सकता है।

मुझे एहसास है कि मैं शायद अपने आप को जो कुछ भी पूछ रहा हूं, उसे इंगित करने वाले लिंक के लिए खुद को खोल रहा हूं, लेकिन मैंने इसे पोस्ट करने से पहले देखा और नहीं पाया है।

किसी भी मदद की सराहना की जाएगी।

+0

यह आपके प्रश्न से पूरी तरह से स्पष्ट नहीं है, लेकिन आप ** केवल ** ** एक स्थिर स्थिर प्रारंभकर्ता * से स्थिर सदस्य तक पहुंचने का प्रयास करते हैं, तो केवल ** ** फियास्को चीज़ से प्रवण हैं। किसी अन्य फ़ंक्शन से इसे एक्सेस करना या नहीं, मुख्य() के बाद कहा जाता है ठीक है – sbk

+0

आपकी टिप्पणी एसबीके के लिए धन्यवाद। मुझे अपने प्रश्न में थोड़ा स्पष्ट होना चाहिए था। मेरा इरादा यह सुनिश्चित करना था कि मैं स्थिर सदस्य के लिए एक अलग सीपीपी फ़ाइल में किसी अन्य वर्ग में स्थिर प्रारंभकर्ता द्वारा उपयोग किया जा रहा था। हालांकि मेरे अन्य वर्गों में से कोई भी वर्तमान में वेक्टर 2 :: getOne() का उपयोग नहीं करता है, विशेष रूप से एक और स्थैतिक सदस्य को शुरू करने के लिए, मेरे पास ऐसे मामले हैं जहां स्थैतिक प्रारंभकर्ताओं की एक श्रृंखला है। मैंने वेक्टर 2 को एक साधारण उदाहरण के रूप में चुना है, इसलिए मैं यहां टिप्पणियों से समझ सकता हूं कि मेरी पूरी परियोजना में रोल करने के लिए सबसे अच्छा पैटर्न है। टिप्पणी के लिए बहुत धन्यवाद। –

उत्तर

10

उनमें से सभी, को छोड़कर, स्थिर प्रारंभिक आदेश फियास्को से पीड़ित हैं। ऐसा इसलिए है क्योंकि आपकी कक्षा एक पीओडी नहीं है। सी ++ 0x में, इस समस्या को कन्स्ट्रक्टर constexpr को चिह्नित करके हल किया जा सकता है, लेकिन सी ++ 03 में ऐसा कोई समाधान नहीं है।

आप सी ++ 03 में समस्या को हल करने निर्माता हटा सकते हैं और

const Vector2 Vector2::ONE = { 1.f, 1.f }; 

का उपयोग कर यह एक पॉड आरंभ कर रहा है प्रारंभ, और सूची में सभी initializers निरंतर अभिव्यक्ति (स्थिर करने के उद्देश्य से कर रहे हैं प्रारंभ)। उनमें से इंटिलाइजेशन किसी कोड को चलाने से पहले होता है जो प्रारंभ होने से पहले इसे एक्सेस कर सकता है।

3.6.2:

स्थिर भंडारण अवधि (3.7.1) के साथ वस्तुओं की जाएगी शून्य प्रारंभ (8.5) से पहले किसी अन्य प्रारंभ होता है। निरंतर अभिव्यक्ति के साथ शून्य-प्रारंभिकरण और प्रारंभिक रूप से सामूहिक प्रारंभिक कहा जाता है; अन्य सभी प्रारंभिक गतिशील प्रारंभिकरण है। स्थिर अभिव्यक्ति अवधि (5.1 9) के साथ प्रारंभिक स्थिर भंडारण अवधि के साथ पीओडी प्रकारों (3.9) के ऑब्जेक्ट्स को किसी गतिशील प्रारंभिक होने से पहले प्रारंभ किया जाएगा।

8.5.1/14:

जब स्थिर भंडारण अवधि के साथ एक समग्र एक ब्रेस संलग्न प्रारंभकर्ता-सूची के साथ आरंभ नहीं हो जाता है, अगर सभी सदस्य प्रारंभकर्ता भाव निरंतर अभिव्यक्ति कर रहे हैं, और कुल मिलाकर एक पॉड प्रकार है, प्रारंभिकरण प्रारंभिक चरण (3.6.2) के दौरान किया जाएगा; अन्यथा, यह अनिर्दिष्ट है कि निरंतर अभिव्यक्ति वाले सदस्यों का प्रारंभिक चरण या प्रारंभिक गतिशील चरण के दौरान होता है।

+0

आपकी टिप्पणी जोहान्स के लिए धन्यवाद। मैं आपको जवाब देने का समय लेने और मेरी 3 संभावनाओं की पुष्टि के लिए तीसरा ही उपयोग करने वाला एकमात्र सुरक्षित है। मैंने पीओडी प्रारंभिक पथ को नीचे जाने का विचार नहीं किया था, इसलिए यह बहुत जानकारीपूर्ण है। यद्यपि मेरे पास अधिक जटिल वर्ग हैं जहां पीओडी दृष्टिकोण काम नहीं करेगा (क्योंकि मेरे सभी वर्गों को पीओडी के रूप में नहीं माना जा सकता है) यह अभी भी बहुत आसान है क्योंकि मैं निश्चित रूप से उन स्थानों को देख सकता हूं जहां मैं इसका उपयोग कर सकता हूं। बहुत धन्यवाद –

+0

मुझे अभी एहसास हुआ कि मैंने कभी आपका जवाब स्वीकार नहीं किया था। इसके बारे में क्षमा करें, लेकिन अब लगभग एक वर्ष बाद –

1

कृपया ध्यान दें कि संभावना 3 धागा सुरक्षित नहीं है।

उदाहरण के लिए देखें "सी ++ स्कॉप्ड स्थैतिक प्रारंभिक उद्देश्य पर थ्रेड-सुरक्षित नहीं है!" http://blogs.msdn.com/b/oldnewthing/archive/2004/03/08/85901.aspx

+1

कृपया ध्यान दें कि यह उत्तर अब सही नहीं है: थ्रेड सुरक्षा अब [मानक द्वारा लगाई गई है] (http://stackoverflow.com/questions/8102125/is-local- स्थिर-चर-आरंभीकरण-धागा सुरक्षित-इन-सी 11) – Arnaud

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