2010-07-27 15 views
13

मैंने हेडर फाइलों में कोड से संबंधित एक सहकर्मी के साथ अभी चर्चा की थी:हेडर फाइलों में कोड हमेशा रेखांकित किया जाएगा?

वह कहता है कि हेडर फ़ाइलों में परिभाषित कोड हमेशा संकलक (जैसे फंक्शन GetNumber() से मेरे उदाहरण शीर्षलेख में) द्वारा रेखांकित किया जाएगा) । मैं कहता हूं कि जब कभी संकलक ऐसा करने का फैसला करता है, तो इसे कभी-कभी रेखांकित किया जाएगा। तो हममें से कौन सा गंदी झूठ बोलने के लिए काम करने के लिए एक केक लाना है? या शायद हम दोनों गलत हैं ...?

MyClass.hpp

class MyClass 
    { 
    public: 
    MyClass(); 
    ~MyClass(); 

    int GetNumber() const 
    { 
    //...; 
    return m_number; 
    }; 

    private: 
    int m_number; 
    }; 
+0

सभी अच्छे उत्तरों के लिए धन्यवाद। इससे निश्चित रूप से मुझे और मेरे सहकर्मी ने इस विषय को स्पष्ट करने में मदद की। हम तय नहीं कर सकता जो केक लाने के लिए है, हालांकि ... ;-) – nabulke

+0

आपको लगता है कि inlineing है पर निर्भर करता है, तो फंक्शन है या नहीं एक शीर्षक में परिभाषित किया गया है इस बात से सहमत नहीं हैं? – adf88

+0

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

उत्तर

10

किसी भी समारोह वर्ग (अपने GetNumber उदाहरण की तरह) में परिभाषित के बजाय घोषित परोक्ष inline है। इसका अर्थ यह है कि inline कीवर्ड का उपयोग करने के लिए यह समतुल्य है, इसलिए हेडर के एकाधिक समावेशन उन कार्यों की कई परिभाषाओं के कारण लिंक त्रुटियों का कारण नहीं बनेंगे।

अधिकांश आधुनिक कंपाइलर inline एक लिंक कमांड के रूप में और कुछ भी नहीं। कुछ कंपाइलर सीएल के __forceinline जैसे मजबूत कीवर्ड प्रदान करते हैं जिसका अर्थ है 'ऐसा करना संभव है तो इसे इनलाइन करें'।

तो आप दोनों सही हैं और दोनों डिग्री एक डिग्री के लिए गलत हैं।

+0

'हेडर के कई समावेशन उन कार्यों की कई परिभाषाओं के कारण लिंक त्रुटियों का कारण नहीं बनेंगे।' यदि कंपाइलर इनलाइन फ़ंक्शन को प्रतिस्थापित करने का निर्णय नहीं लेता है तो क्या होगा? क्या यह अभी भी लिंकिंग त्रुटि उत्पन्न कर रहा है? – Deqing

+0

फ़ंक्शन 'इनलाइन' को चिह्नित करने से संकलक को त्रुटि को छोड़ने का कारण नहीं होता है, यदि यह संकलित की एकाधिक समान परिभाषाओं को देखता है चाहे संकलन कोड को इनलाइन करने के लिए चुनता है या नहीं। –

1

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

1

संकलक निर्णय लेता है। यहां तक ​​कि _inline का उपयोग केवल उस कंपाइलर को बताता है जिसे आप इनलाइन कोड पसंद करते हैं, लेकिन कंपाइलर की लागत/लाभ विश्लेषक अन्यथा निर्णय ले सकता है।

यदि आप कोड इनलाइन बनाने के लिए Microsoft C++ का उपयोग कर रहे हैं, तो आप _forceinline का उपयोग कर सकते हैं, लेकिन इसके परिणामस्वरूप बड़ी बाइनरी हो सकती है।

+0

+1: पता नहीं था _forceinline – nabulke

3

यह "इनलाइनिंग" से आपका क्या मतलब है इस पर निर्भर करता है। यदि किसी हेडर फ़ाइल में कुछ परिभाषित किया गया है, तो इसे प्रत्येक संकलन इकाई में अलग से संकलित किया जाएगा जिसमें इसे शामिल किया गया है। चाहे कॉल पर कॉल को संकलित किया जाएगा, कंपाइलर तक होगा।

7

आपका दोस्त गलत है, आप सही हैं।

इनलाइनिंग इस बात पर निर्भर नहीं है कि कोड कहां है (हेडर या नहीं)। प्रीप्रोसेसिंग के बाद कोई हेडर या गैर-हेडर नहीं होता है। पूरी इकाई एक फ़ाइल है, इसमें सभी शामिल सामग्री शामिल हैं।

जीसीसी पूर्वप्रक्रमक चल रहा है तो आप देखेंगे का प्रयास करें:

gcc -E some_source_file_with_includes 
+5

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

+1

+1: – nabulke

+0

प्रीप्रोसेसिंग के बाद पूरी इकाई के बारे में आपकी टिप्पणी पसंद आई, मैंने हेडर फाइलों के बारे में लिखा, यदि परिभाषा हेडर के अंदर है या नहीं, तो कोई फर्क नहीं पड़ता। ध्यान से पढ़ें। – adf88

2

कक्षा सदस्य समारोह (केवल घोषित करने के लिए के रूप में विरोध) परिभाषित वर्ग 'परिभाषा परोक्षinline हैं। हेडर में अन्य कोड नहीं है।

आप आसानी से इस जाँच कर सकते हैं: एक हैडर और दो कार्यान्वयन फाइलों के साथ एक छोटी सी सी ++ प्रोजेक्ट बना, एक समारोह

void print(std::ostream& os) 
{ 
    os << "Hello, world!\n"; 
} 
शीर्षक में

को परिभाषित करने और दोनों कार्यान्वयन फाइलों में है कि शीर्ष लेख शामिल हैं। लिंकर अब शिकायत करेगा कि फ़ंक्शन को दो बार परिभाषित किया गया है। फ़ंक्शन परिभाषा से पहले inline डालें और त्रुटि गायब हो जाएगी।

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

const int answer = 42; 
एक हैडर लिंकर नहीं होगा में

, answer की कई परिभाषाएं के बारे में शिकायत करते हुए

int question; 

इच्छा।

3

असल में दोनों सही हैं। जिस तरह से आप लोगों का मतलब थोड़ा अलग है। (मुझे लगता है)

इनलाइन समारोह के लिए सी ++ मानक डॉक से

,

  1. एक समारोह घोषणा (8.3.5, 9.3, 11.4 ) एक इनलाइन विनिर्देशक के साथ एक इनलाइन समारोह की घोषणा की।

2. कक्षा परिभाषा के भीतर परिभाषित एक फ़ंक्शन एक इनलाइन फ़ंक्शन है।

तो के रूप में अपने सहयोगी ने कहा, यह वास्तव में इनलाइन समारोह है। सामान्य कार्य कॉल के बजाय इनलाइन समारोह के लिए

लेकिन कोड प्रतिस्थापन संकलक पर निर्भर है। (मुझे उम्मीद है कि आपका मतलब है) भले ही कंपाइलर प्रतिस्थापित नहीं करता है, फिर भी यह एक इनलाइन फ़ंक्शन है।

आशा है कि यह आपकी चिंता को साफ करता है ..

+0

इनलाइन फ़ंक्शन को रेखांकित करने की आवश्यकता नहीं है, गैर इनलाइन फ़ंक्शन को रेखांकित किया जा सकता है। कंपाइलर फैसला करते हैं। इसके अलावा, आप इस विषय से संबंधित उदाहरण के विनिर्देशों के बारे में बात कर रहे हैं। – adf88

+0

@ adf88, यही मेरा मतलब था। कोड प्रतिस्थापन संकलक द्वारा तय किया जाता है लेकिन समारोह वास्तव में एक इनलाइन फ़ंक्शन है। सभी इनलाइन फ़ंक्शंस को कंपाइलर द्वारा प्रतिस्थापित कोड की आवश्यकता नहीं है .. – liaK

+0

फ़ंक्शन इनलाइन फ़ंक्शन (सी ++ भाषा तरीके से) के बारे में नहीं है। यह इस बारे में है कि फ़ंक्शन को कंपाइलर द्वारा रेखांकित किया जाएगा। – adf88

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