2012-01-09 15 views
33

मुझे सी ++ के बारे में क्या पता है कि वैश्विक उदाहरणों के निर्माण (और विनाश) का आदेश ग्रहण नहीं किया जाना चाहिए।क्या std :: cout प्रारंभ करने की गारंटी है?

जबकि मैं वैश्विक उदाहरण के साथ कोड लिख रहा हूं जो std::cout कन्स्ट्रक्टर & विनाशक में उपयोग करता है, मुझे एक प्रश्न मिला।

std::cout आईस्ट्रीम का वैश्विक उदाहरण भी है। std::cout किसी भी अन्य वैश्विक घटनाओं से पहले शुरू किया जाने की गारंटी है?

मैंने एक साधारण परीक्षण कोड लिखा और यह पूरी तरह से काम करता है, लेकिन फिर भी मुझे नहीं पता कि क्यों।

#include <iostream> 

struct test 
{ 
    test() { std::cout << "test::ctor" << std::endl; } 
    ~test() { std::cout << "test::dtor" << std::endl; } 
}; 

test t; 

int main() 
{ 
    std::cout << "Hello world" << std::endl; 
    return 0; 
} 

यह

test::ctor 
Hello world 
test::dtor 

वहाँ किसी भी संभावना है कि कोड अपेक्षित ढंग से नहीं चलता है प्रिंट है?

+1

से संबंधित http://stackoverflow.com/questions/6919593/is-cout-guaranteed-available-during-static-deinitialization जो उत्तर में निर्माण को भी शामिल करता है। – adl

+0

वैश्विक दायरे में स्थिर भंडारण अवधि वस्तुओं का प्रारंभिक क्रम ग्रहण नहीं किया जा सकता है लेकिन प्रारंभिक क्रम को मजबूर करने के लिए चाल हैं। –

+0

पीएस।यह भी ध्यान दें कि विनाश के आदेश की गारंटी है (निर्माण के विपरीत)। –

उत्तर

36

उत्तर यदि आप C++ 03 या C++ 11 का उपयोग कर रहे हैं, तो इसका उत्तर अलग-अलग होता है।

सी ++ 11 में, आपका कोड काम करने की गारंटी है, लेकिन सी ++ 03 में यह अनिर्दिष्ट है; आपकी एकमात्र गारंटी यह है कि main() दर्ज किया गया है, मानक धाराओं को शुरू किया गया था। (जैसा कि कहा गया है, सभी मुख्य धारा कार्यान्वयन उन्हें पहले किसी भी गतिशील प्रारंभ चलाने के लिए प्रारंभ, उन्हें उपयोग करने के लिए ठीक हो जाता है।)

तुम इतनी तरह, एक std::ios_base::Init वस्तु का निर्माण करके प्रारंभ मजबूर कर सकते हैं:

#include <iostream> 

struct test 
{ 
    test() { std::cout << "test::ctor" << std::endl; } 
    ~test() { std::cout << "test::dtor" << std::endl; } 

private: 
    std::ios_base::Init mInitializer; 
}; 

test t; 

int main() 
{ 
    std::cout << "Hello world" << std::endl; 
    return 0; 
} 

अब जब test संरचनाएं, यह mInitializer शुरू करती है और गारंटी देता है कि धाराएं उपयोग करने के लिए तैयार हैं।

सी ++ 11 ने #include <iostream> के प्रत्येक उदाहरण static std::ios_base::Init __unspecified_name__; के बाद अभिनय करके थोड़ा सा परेशान व्यवहार तय किया। यह स्वचालित रूप से गारंटी देता है कि धाराएं उपयोग करने के लिए तैयार हैं।

+2

सी ++ 03 स्पष्ट आशय (के रूप में पाद टिप्पणी द्वारा इंगित) में एसटीडी की गारंटी करने के :: CIN/std :: अदालत वस्तुओं को पूरी तरह से अन्य वस्तुओं से पहले निर्माण कर रहे हैं है। –

10

§27.3/2 के अनुसार:

वस्तुओं [std :: CIN, std :: अदालत, आदि] निर्माण कर रहे हैं, और संघों के लिए या पूर्व कुछ समय में स्थापित कर रहे हैं पहले के दौरान कक्षा ios_base का एक ऑब्जेक्ट :: इनिट का निर्माण किया गया है, और किसी भी मामले में मुख्य के शरीर को निष्पादन शुरू होने से पहले।

+1

जो अन्य स्थैतिक वस्तुओं के सापेक्ष 'std :: cout' के निर्माण के आदेश के बारे में कुछ भी नहीं कहता है। –

+10

@ बेसिलस्टारनकेविच: सच्चाई का क्रमबद्ध करें, लेकिन फुटनोट 265 (§27.3/2 से संदर्भित) कहता है कि इसे काम करना चाहिए: "स्थैतिक वस्तुओं के लिए निर्माता और विनाशक इन ऑब्जेक्ट्स को स्टडीन से इनपुट पढ़ने या स्टडआउट या स्टडर में आउटपुट लिखने के लिए एक्सेस कर सकते हैं।" यह मानक नहीं हो सकता है, लेकिन कम से कम * इरादा * स्पष्ट रूप से बताता है कि उसका कोड काम करना चाहिए। –

+3

@ बेसिलस्टारनकेविच: यह वास्तव में करता है। अनुच्छेद जारी है: "अनुवाद इकाई में समेत परिणाम जैसे ने स्थिर भंडारण अवधि के साथ ios_base :: Init के एक उदाहरण को परिभाषित किया है।" और चूंकि एक ही अनुवाद इकाई में स्थैतिक गैर-स्थानीय चर घोषित किए जाने के क्रम में आरंभ किए जाते हैं, इसलिए आपकी अन्य गैर-स्थानीय सांख्यिकी से पहले 'कोउट' शुरू किया गया है। (आप यह मानते हुए '# शामिल ' इससे पहले कि आप अपने चर, जो मैं ईमानदारी से आशा है कि घोषित) – knatten

2

आपका प्रश्न स्थैतिक वस्तुओं के निर्माण के आदेश के बारे में है। मेरा मानना ​​है कि भाषा विनिर्देश इसे अनिर्धारित छोड़ देता है।

जीसीसी में init_priority ऑर्डर के साथ खेलने के लिए विशेषता है।

और मुझे विश्वास है कि आपको अभ्यास में इतना चिंता नहीं करनी चाहिए।

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