2009-12-01 7 views
117

जी ++ -वॉल विकल्प में शामिल हैं -प्रॉर्डर। यह विकल्प क्या नीचे वर्णित है। यह मेरे लिए स्पष्ट नहीं है कि कोई क्यों परवाह करेगा (विशेष रूप से इसे डिफ़ॉल्ट रूप से चालू करने के लिए पर्याप्त है - वाल)।g ++ -Wreorder का क्या मतलब है?

 
-Wreorder (C++ only) 
    Warn when the order of member initializers given in the code does not 
    match the order in which they must be executed. For instance: 

    struct A { 
     int i; 
     int j; 
     A(): j (0), i (1) { } 
    }; 

    The compiler will rearrange the member initializers for i and j to 
    match the declaration order of the members, emit-ting a warning to that 
    effect. This warning is enabled by -Wall. 

उत्तर

195

पर विचार करें:

struct A { 
    int i; 
    int j; 
    A() : j(0), i(j) { } 
}; 

अब i, शून्य किसी अज्ञात मूल्य के लिए आरंभ नहीं हो जाता नहीं।

वैकल्पिक रूप से, i की शुरुआत के कुछ दुष्प्रभाव हो सकते हैं जिसके लिए आदेश महत्वपूर्ण है। जैसे

A(int n) : j(n++), i(n++) { } 
+60

यह वास्तव में प्रलेखन में उदाहरण होना चाहिए। –

+3

धन्यवाद। सरल प्रारंभकर्ताओं के साथ हमारे अधिकांश प्रकार पीओडी प्रकार होने के कारण यह मेरे लिए नहीं हुआ। आपका उदाहरण g ++ मैन्युअल उदाहरण से काफी बेहतर है। –

+0

इसका उदाहरण जवाब बहुत उलझन में है। जब मैंने इसका परीक्षण किया तो मैंने पाया कि 'i' ** ** को लगातार 0 से शुरू किया गया था, जो ऐसा लगता है कि कुछ भी गलत नहीं है। लेकिन अगर आप '100' की तरह कुछ उपयोग करते हैं तो आप देखते हैं कि 'j'' 100' है और 'i'' 0' है। मुझे पता है कि यह शायद कंपाइलर के कारण है लेकिन मैं उबंटू के साथ जो भी डिफ़ॉल्ट जी ++ प्राप्त करता हूं, इसलिए यह एक आम घटना होनी चाहिए। –

9

यदि आपके प्रारंभकर्ताओं के साइड इफेक्ट्स हैं तो यह आपको काट सकता है। पर विचार करें:

int foo() { 
    puts("foo"); 
    return 1; 
} 

int bar() { 
    puts("bar"); 
    return 2; 
} 

struct baz { 
    int x, y; 
    baz() : y(foo()), x(bar()) {} 
}; 

ऊपर, "बार" तो "foo" प्रिंट होगा भले ही सहज एक ग्रहण करेंगे कि आदेश के रूप में प्रारंभकर्ता सूची में लिखा है।

वैकल्पिक रूप से, यदि x और y कुछ उपयोगकर्ता-परिभाषित प्रकार के निर्माता हैं, तो कन्स्ट्रक्टर के पास भी गैर-स्पष्ट परिणाम के साथ साइड इफेक्ट्स हो सकते हैं।

यह तब भी प्रकट हो सकता है जब एक सदस्य के लिए प्रारंभकर्ता दूसरे सदस्य का संदर्भ देता है।

29

समस्या यह है कि किसी को कन्स्ट्रक्टर में सदस्य प्रारंभकर्ताओं की सूची दिखाई दे सकती है, और लगता है कि उन्हें उस क्रम में निष्पादित किया गया है (जे पहले, फिर i)। वे नहीं हैं, सदस्यों को कक्षा में परिभाषित करने के क्रम में उन्हें निष्पादित किया जाता है।

मान लें कि आपने A(): j(0), i(j) {} लिखा है। कोई इसे पढ़ सकता है, और सोचता है कि मैं मान 0 के साथ समाप्त होता हूं। ऐसा नहीं होता है, क्योंकि आपने इसे जे के साथ शुरू किया है, जिसमें जंक शामिल है क्योंकि इसे स्वयं शुरू नहीं किया गया है।

चेतावनी आपको A(): i(j), j(0) {} लिखने की याद दिलाती है, जो उम्मीद है कि बहुत अधिक फिश लगती है।

+0

वास्तव में मछली पकड़ता है/गंध करता है! :) निश्चित रूप से कोड गंध :) आपके स्पष्ट स्पष्टीकरण के लिए धन्यवाद जो बिंदु के लिए सही है। :) – Will

+0

अच्छी तरह से समझाया, यह सबसे अच्छा जवाब होना चाहिए! – Aaron

+0

"... आपको ए() लिखने की याद दिलाता है: i (j), j (0) {} ..." मेरा सुझाव है कि यह आपको इस विशेष मामले में कक्षा के सदस्यों को पुन: व्यवस्थित करने की याद दिलाता है। –

5

चेतावनी मौजूद है क्योंकि यदि आप केवल निर्माता को पढ़ते हैं, तो ऐसा लगता है कि ji से पहले प्रारंभ हो रहा है। यह एक समस्या है, तो एक

struct A { 
    int i; 
    int j; 
    A(): j (0), i (this->j) { } 
}; 

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

9

अन्य उत्तरों ने कुछ अच्छे उदाहरण दिए हैं जो चेतावनी के विकल्प को उचित ठहराते हैं। मैंने सोचा कि मैं कुछ ऐतिहासिक संदर्भ प्रदान करूंगा। सी ++ के निर्माता, Bjarne Stroustrup, अपनी पुस्तक The C++ programming language (3 संस्करण, पृष्ठ 259) में बताते हैं: स्वयं के निर्माता निष्पादित किया जाता है

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

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