2010-06-24 10 views
7

मुख्य रूप से घोषित कक्षाओं के रचनाकारों को मुख्य प्रवेश करने से पहले बुलाया जाता है। हालांकि यह कोड के नए पाठक को भ्रमित कर सकता है क्योंकि यह बहुत बार किया जाता है, क्या यह आवश्यक रूप से एक बुरा विचार है?सी ++ में, क्या यह कोड लिखने के लिए अच्छा रूप है जो मुख्य() से पहले निष्पादित करता है?

+10

हर बार जब आप ग्लोबल्स का उपयोग करते हैं, तो भगवान एक बिल्ली का बच्चा मारता है। – ereOn

+7

नहीं मैं नहीं ..... –

+0

आप नहीं करते हैं, लेकिन मैं करता हूं .... –

उत्तर

18

यह आवश्यक नहीं है एक बुरा विचार है, लेकिन आमतौर पर, हाँ।

सबसे पहले, यह वैश्विक डेटा है, और वैश्विक आम तौर पर एक बुरी बात कर रहे हैं। आपके पास जितनी अधिक वैश्विक स्थिति है, उतना कठिन यह आपके कार्यक्रम के कारण बनता है।

दूसरा, सी ++ अलग अनुवाद इकाइयों में परिभाषित स्थिर वस्तुओं के intialization आदेश (सीपीपी फ़ाइलें) की गारंटी नहीं है - तो यदि वे एक दूसरे पर निर्भर करते हैं, तो आप मुसीबत में हो सकता है।

+1

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

+0

इसके अलावा, ग्लोबल्स का थ्रेडिंग कम से कम कहने के लिए असुरक्षित है और उन्हें एक्सेस करना धीमा है (यहां तक ​​कि ढेर तक पहुंचना तेज है)। विशाल, विशाल, विशाल बहुमत मामलों में ग्लोबल्स एक बुरा विचार है। वस्तुत: अपवाद भी हैं। – Puppy

+0

रचनाकार ऑर्डर-निर्भर नहीं हैं और कुछ सौम्य प्रारंभिक कार्य करते हैं। धागा ध्यान से नियंत्रित किया जाता है। – Bruce

1

संदिग्ध रूप से होने के अलावा - यह कुछ प्लेटफॉर्म के लिए पोर्टेबल नहीं होगा।

1

जैसा कि आप इंगित करते हैं, इसकी अनुमति है। पिछली कंपनी में मैंने काम किया, जब ऐसी स्थिति उत्पन्न होगी, हमने इसे मुख्य() पर उचित टिप्पणी जोड़ने की नीति बनाई है ताकि यह संकेत दिया जा सके कि यह किस चर पर लागू होता है। यदि आपके पास खराब स्थिति है, तो इसे सर्वश्रेष्ठ बनाने का प्रयास करें।

7

हाँ, यह बुरा है। चूंकि आपके पास अपवादों को पकड़ने और उनके साथ सौदा करने का कोई तरीका नहीं होगा, इसलिए डिफ़ॉल्ट हैंडलर का उपयोग किया जाएगा। सी ++ कि समाप्त बुला मतलब है ...

में

उदाहरण: सामग्री a.cpp

#include <stdexcept> 

int f() { throw std::runtime_error("boom"); return 42; } 
int i = f(); 

int main(int argc, char* argv[]) 
{ 
    return 0; 
} 

आउटपुट की: g++ a.cpp && ./a.out

terminate called after throwing an instance of 'std::runtime_error' 
    what(): boom 
Aborted (core dumped) 

आप अपने मुख्य में जोड़ने के एक try ... catch कोशिश कर सकते हैं, कि मदद नहीं करेगा ।

संपादित करें: Jalf के अंक भी मान्य हैं। उसकी सलाह सुनो।

+0

मुख्य() कोशिश करें {...} पकड़ें (...) {...}? –

+0

मुझे नहीं लगता कि यह उदाहरण 'int i = f();' के कारण कानूनी है। जहां तक ​​मुझे पता है वैश्विक ग्लोबल वैरिएबल घोषित करते समय आप फ़ंक्शन को कॉल नहीं कर सकते हैं। –

+0

@Alexandre - हम मुख्य प्रारंभ से पहले कोड के बारे में बात कर रहे हैं। तो मुख्य में एक कोशिश/पकड़ इसे प्राप्त नहीं कर सकता क्योंकि इस कोड को निष्पादित करने पर प्रयास दर्ज नहीं किया गया है। –

0

गैर-तुच्छ कन्स्ट्रक्टर और विनाशकों के साथ वैश्विक/स्थिर वस्तुओं का उपयोग भयानक है। मैंने पर्याप्त विशाल सॉफ्टवेयर परियोजनाएं देखीं जो वैश्विक/स्थैतिक वस्तुओं और सिंगलटन के अनियंत्रित उपयोग की वजह से खुद को आपदा में पाई गईं।

समस्या तथ्य यह है कि यह कोड है कि main बाहर चलाया जाता है है नहीं है। यह है कि उन वस्तुओं का निर्माण अनियंत्रित आदेश में किया गया है और नष्ट कर दिया गया है।

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

+0

std :: cout वैश्विक है। – ChrisW

+0

@ChrisW: आप std :: cout को नष्ट नहीं करना चाहते हैं ... क्या आप ?? – smerlin

+0

@smerlin - नहीं, लेकिन यह एक वैश्विक चर का एक उदाहरण है; जो बनाया गया है। मेयर्स ने एक उदाहरण दिया (जिसे उन्होंने कहा कि std :: cout कार्यान्वयन में उपयोग किया जाता है) जिसमें अनुक्रम को नियंत्रित करने के लिए ग्लोबल्स का निर्माण किया जाता है; या इसके बजाय, यह गारंटी देने के लिए कि वैश्विक उपयोग करने से पहले वैश्विक बनाया गया है, भले ही आप वैश्विक हों और यदि आप जिस चीज का उपयोग कर रहे हैं (उदा। std :: cout) एक अलग अनुवाद इकाई में है। – ChrisW

0

यह पर खराब फॉर्म नहीं है, और यह भ्रमित नहीं है। स्टेटिक प्रारंभिक भाषा की एक जानबूझकर विशेषता है। जब आपको आवश्यकता हो तो इसका इस्तेमाल करें। ग्लोबल्स के साथ ही। जब आपको आवश्यकता हो तो उनका इस्तेमाल करें। किसी भी सुविधा की तरह, यह जानना कि यह कब उचित है और इसकी सीमाओं को जानना एक मजबूत प्रोग्रामर होने का हिस्सा है।

खराब फॉर्म ग्लोबल्स या स्थैतिक प्रारंभिकरण से बचने के लिए अन्यथा पूरी तरह से ठीक कार्यक्रम का पुनर्गठन कर रहा है।

+0

इस तरह का मानना ​​है कि आप पहले से लिखित परियोजना के साथ काम कर रहे हैं; मूल प्रश्न वास्तव में अनुवांशिक है, मूल्यांकन नहीं। –

0

मुझे अब तक यह कहना होगा कि यह गैर-पीओडी के लिए खराब फॉर्म है, खासकर यदि आप प्राथमिक रूप से प्रारंभिक आदेश की समस्याओं के कारण टीम में काम कर रहे हैं जो आसानी से उत्पन्न हो सकता है।

// the following invokes undefined behavior. 
static bool success=cout<<"hello world\n"; 

लोग आम तौर पर इसके बाद के संस्करण की तरह कोड लिखने नहीं है, लेकिन पर विचार करता है, तो सफलता एक और समारोह के रिटर्न मान पर प्रारंभ किया गया था। अब किसी ने भी उस समारोह में कोउट या सीर या किसी अन्य वैश्विक वस्तु का उपयोग करने का लुत्फ उठाया है, वही अपरिभाषित व्यवहार का आह्वान किया है।

निर्माणकर्ता और विनाशकर्ता साथ उपयोगकर्ता परिभाषित प्रकार के लिए, वैकल्पिक पद्धति पर विचार जहां पहुँच प्रारंभ है:

static Foo& safe_static() 
{ 
    static Foo f; 
    return f; 
} 

दुर्भाग्य से यह भी है धागा सुरक्षा के साथ समस्याओं ताकि किसी प्रकार का ताला तंत्र निर्माण के लिए आवश्यक है 'एफ' के अगर आप एक साथ सुरक्षित_स्टैटिक तक पहुंच रहे हैं।

उसने कहा, मुझे लगता है कि किसी को चीजों को सरल रखने की कोशिश करनी चाहिए। दुर्भाग्यवश जब फ़ाइल स्कोप पर परिभाषित उपयोगकर्ता परिभाषित ऑब्जेक्ट्स की बात आती है, तो यह अनिर्धारित व्यवहार में भागना बहुत आसान है। उपरोक्त सुरक्षित_स्टैटिक जैसे कुछ लिखने के लिए आवश्यक अतिरिक्त अतिरिक्त प्रयास बहुत सारे सिरदर्द को रोक सकता है।

अपवाद एक और बिंदु हैं। यदि आपकी स्थिर वस्तुएं उनके कन्स्ट्रक्टर से बाहर फेंकती हैं, तो आपके पास अपवाद को पकड़ने का कोई तरीका नहीं है। यदि आप चाहते हैं कि आपका एप्लिकेशन वास्तव में मजबूत हो और स्टार्टअप त्रुटियों को भी संभाल लें, तो आपको अपने कोड को सावधानी से तैयार करना होगा (उदा: आपके द्वारा फ़ाइल स्कोप पर बनाए गए ऑब्जेक्ट्स के लिए कन्स्ट्रक्टर में ब्लॉक को आज़माएं/पकड़ें ताकि अपवाद फेंक दिया न जाए सीटीओ के बाहर और फेंकने वाली प्रारंभिक सूचियों से बचें)।

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

यह वास्तव में संभावित सिरदर्द आईएमओ के लायक नहीं है, और यह एक समस्या है जो ठीक करने से बचने के लिए बहुत आसान है।

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