2012-08-31 10 views
43

मैं आज कुछ कोड लिख रहा था और एक अजीब संकलन त्रुटि मिली, जो कि घोषित किए गए अनुसार अलग-अलग क्रम में सदस्य चर को प्रारंभ करने के कारण होता है।मुझे सदस्य चर को किस क्रम में घोषित किया जाना चाहिए?

उदाहरण:

class Test { 
    int a; 
    int b; 

public: 
    Test() : b(1), a(2) { 
    } 
}; 

int main() { 
    Test test; 
    return 0; 
} 
फिर अगर मैं इसे संकलन -Werror -Wall साथ

:

$ g++ -Werror -Wall test.cpp 
test.cpp: In constructor ‘Test::Test()’: 
test.cpp:3:9: error: ‘Test::b’ will be initialized after [-Werror=reorder] 
test.cpp:2:9: error: ‘int Test::a’ [-Werror=reorder] 
test.cpp:6:5: error: when initialized here [-Werror=reorder] 
cc1plus: all warnings being treated as errors 

मुझे लगता है कि -Wall स्पष्ट रूप से जीसीसी पूछ रहा है से शीर्ष पर चेतावनी के साथ जाने के लिए, लेकिन मैं वहाँ मान उन सभी के लिए एक कारण है। तो, सदस्य चर शुरू करने का आदेश कैसे मायने रख सकता है?

+2

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

उत्तर

71

कारण यह है कि वे आपके वर्ग में घोषित किए गए क्रम में शुरू किए गए हैं, न कि आप उन्हें निर्माता में प्रारंभ करते हैं और यह आपको चेतावनी देता है कि आपके कन्स्ट्रक्टर का ऑर्डर नहीं उपयोग किया जाएगा।

यह त्रुटियों को रोकने में मदद करने के लिए है जहां b की शुरुआत a या इसके विपरीत पर निर्भर करती है।

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

27

आपको नहीं करना चाहिए क्योंकि यह पठनीयता कम करता है और संभावित रूप से भ्रामक है।

अगर तुमने किया था:

Test() : b(1), a(b) {} 

यह जाहिर होता है कि b तो a दोनों 1 लिए स्थापित किया गया है, जबकि वास्तव में b की अप्रारंभीकृत मूल्य a प्रारंभ करने से पहले b1 को आरंभ नहीं हो जाता प्रयोग किया जाता है।

+2

+1 यह दिखाने के लिए कि ऑर्डर वास्तव में क्यों मायने रखता है और अगर किसी ने ऑर्डरिंग मान ली है तो क्या गलत हो सकता है, जिसे उन्होंने कन्स्ट्रक्टर में घोषित किया है। – atuljangra

12

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

उदाहरण के लिए, कोड

Test(): b(42), a(b) {} 

पर विचार यह एक बग क्योंकि ab से पहले आरंभ नहीं हो जाता है, लेकिन यह ठीक लग रहा है। आप घोषणा के क्रम में (जो आरंभीकरण के आदेश है) में यह लिखते हैं, बग स्पष्ट हो जाता है:

Test(): a(b), b(42) {} 

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

36

मुझे सदस्य चर को किस क्रम में घोषित किया जाना चाहिए?

सदस्यों उसी क्रम में वे घोषणा की जाती है, चाहे आप इसे या नहीं चाहते में प्रारंभ कर दिया जाएगा। चेतावनी आपको बता रही है कि जिस आदेश के लिए आप पूछ रहे हैं वह प्रारंभिकरण के निष्पादन के वास्तविक क्रम से अलग है।

+3

+1 एक संक्षिप्त, टू-द-पॉइंट उत्तर के लिए +1 जो "कंपाइलर" शब्द का उपयोग नहीं करता है। –

+1

अच्छा जवाब। क्या हम मान सकते हैं कि यह केवल सी ++ मानक है यह सुनिश्चित कर रहा है कि सभी रचनाकार निश्चित रूप से संकलित हों, या क्या कुछ तकनीकी/प्रदर्शन कारण है कि सदस्यों को हमेशा घोषित किए जाने वाले क्रम में प्रारंभ किया जाना चाहिए? –

+4

@XavierHolt: भाषा में, सभी गतिशील रूप से आवंटित वस्तुओं के लिए, निर्माण और विनाश का आदेश उलट दिया गया है। अगर प्रारंभिक क्रम प्रारंभकर्ता सूची द्वारा निर्धारित किया गया था तो कई रचनाकारों के साथ कक्षा में प्रारंभिकरण का क्रम परिभाषित नहीं किया जाएगा और सदस्यों के विनाश के आदेश को परिभाषित नहीं किया जाएगा। निर्माण/विनाश का आदेश उलट दिया गया है यह सुनिश्चित करने के लिए कि यदि कोई वस्तु दूसरे पर निर्भर करती है, तो दूसरा पहले से पहले नष्ट नहीं होगा। –

5

मुझे एहसास है कि -वॉल स्पष्ट रूप से चेतावनी के साथ शीर्ष पर जाने के लिए जीसीसी से पूछ रहा है, लेकिन मुझे लगता है कि उन सभी के लिए एक कारण है।

-Wall बस एक शुरुआत है। नाम का क्या अर्थ है इसके विपरीत, -वॉल सभी चेतावनियों को सक्षम नहीं करता है। कुछ चेतावनियां हैं जो तर्कसंगत रूप से "शीर्ष पर" हैं, लेकिन वे निश्चित रूप से चेतावनियां हैं -Wall सक्षम नहीं है। मैं हमेशा -Wall प्लस दूसरों का उपयोग करता हूं।

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

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