2009-12-07 20 views
5

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

उत्तर

15

सच नहीं है कि "एक वर्ग के हेडर फाइल के अंदर एक C++ समारोह को परिभाषित समारोह इनलाइन हैं"। एक वर्ग परिभाषा के अंदर एक फ़ंक्शन को परिभाषित करना (जो कहने के लिए, केवल एक घोषणा के बजाय फ़ंक्शन का शरीर प्रदान करना) इसे इनलाइन बनाता है। "इसे इनलाइन बनाता है" से, मेरा मतलब है कि यह इनलाइन कीवर्ड देने जैसा ही है। लेकिन कक्षा परिभाषाओं को हेडर में होना जरूरी नहीं है, और हेडर में कक्षा परिभाषाओं की तुलना में अन्य चीजें हो सकती हैं।

तो इस उदाहरण में, foo फ़ंक्शन अंतर्निहित रूप से इनलाइन है। समारोह bar परोक्ष इनलाइन नहीं है:

struct Foo { 
    void foo() {} 
    void bar(); 
}; 

void Foo::bar() {} 

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

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

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

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

+1

+1। –

3

सी ++ कंपाइलर्स यह चुनने के लिए स्वतंत्र हैं कि इनलाइन क्या होगा और क्या नहीं होगा, इससे कोई फर्क नहीं पड़ता कि आप उन्हें क्या संकेत देते हैं। इससे कोई फर्क नहीं पड़ता कि फ़ंक्शन किसी वर्ग का हिस्सा है या नहीं, या यह हेडर फ़ाइल या स्रोत फ़ाइल में है या नहीं; संकलक अपने निर्णय लेने के दौरान उन चीजों पर ध्यान नहीं देता है।

+1

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

+0

@ करल: सच है, लेकिन सवाल विपरीत स्थिति के बारे में था। मुझे लगता है कि मेरा जवाब थोड़ा और सावधानीपूर्वक शब्द हो सकता था। 'इनलाइन' कीवर्ड के दूसरे प्रभाव का उल्लेख करने के लिए –

0

आप एक हेडर फाइल में एक नि: शुल्क गैर टेम्पलेट समारोह की परिभाषा देते हैं, तो आप प्रत्येक .cpp फ़ाइल है कि शीर्ष लेख (प्रत्यक्ष या परोक्ष) भी शामिल है में एक समारोह परिभाषा के साथ खत्म हो जाएगा। यह लिंक करते समय समस्याएं पैदा कर सकता है।

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

1

नहीं है, हमेशा नहीं। संकलक एक संकेत के रूप में यह व्यवहार करता है, सिर्फ inline कीवर्ड की तरह, लेकिन यह ज्यादातर अपने आप ही फैसला करता है, क्योंकि यह आप से बेहतर लागत और लाभ हो सकता है क्या जानता है। कोड को रेखांकित करने से फ़ंक्शन कॉल ओवरहेड से बचा जाता है, लेकिन कोड को बड़ा बनाता है, जिसमें निर्देश कैश पर नकारात्मक प्रदर्शन प्रभाव पड़ता है।

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

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

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