मुझे फ़ंक्शन / विधि के लिए कीवर्ड 'इनलाइन' कब लिखना चाहिए?


562

मुझे inlineC ++ में फ़ंक्शन / विधि के लिए कीवर्ड कब लिखना चाहिए ?

कुछ उत्तरों को देखने के बाद, कुछ संबंधित प्रश्न:

  • C ++ में किसी फ़ंक्शन / पद्धति के लिए मुझे 'इनलाइन' कीवर्ड कब नहीं लिखना चाहिए ?

  • कंपाइलर को पता नहीं चलेगा कि फंक्शन / मेथड 'इनलाइन' कब बनाया जाएगा?

  • क्या कोई फर्क पड़ता है अगर कोई फ़ंक्शन / विधि के लिए 'इनलाइन' लिखने पर एप्लिकेशन को मल्टीथ्रेड किया जाता है ?


40
यदि आप किसी हेडर में फ़ंक्शन को परिभाषित करते हैं तो आपको इनलाइन घोषित करना होगा। अन्यथा आपको फ़ंक्शन की कई परिभाषाओं के बारे में लिंकर त्रुटियां मिलेंगी।
मार्टिन न्यूयॉर्क

15
@ मर्टिन: जब तक वह क्लास की परिभाषा में न हो, तब तक वह पिकी है।
डेविड थॉर्नले

20
@ डेविड: अतिरिक्त पिकी होने के लिए, ऐसा केवल इसलिए है क्योंकि इस तरह के कार्य निहित हैं inline(9.3 / 2)।
कक्षा


C ++ FAQ में इनलाइन फ़ंक्शंस भी देखें । उनके पास इनलाइन का बहुत अच्छा इलाज है।
jww

जवाबों:


882

ओह यार, मेरा एक पालतू जानवर।

inline और अधिक पसंद है staticexternसंकलक को निर्देश देने या बताने से आपके कार्यों को इनलाइन करना पसंद है। extern, static, inlineलिंकेज निर्देशों, लिंकर, नहीं संकलक द्वारा लगभग विशेष रूप से किया जाता है।

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

  • static- चर / फ़ंक्शन नाम का अन्य अनुवाद इकाइयों में उपयोग नहीं किया जा सकता है। लिंकर को यह सुनिश्चित करने की आवश्यकता है कि यह गलती से किसी अन्य अनुवाद इकाई से सांख्यिकीय रूप से परिभाषित चर / फ़ंक्शन का उपयोग नहीं करता है।

  • extern- इस अनुवाद इकाई में इस चर / फ़ंक्शन नाम का उपयोग करें लेकिन अगर यह परिभाषित नहीं है तो शिकायत न करें। लिंकर इसे छांट लेगा और यह सुनिश्चित कर लेगा कि सभी कोड जो कुछ बाहरी प्रतीक का उपयोग करने की कोशिश करते हैं, उनका पता है।

  • inline- यह फ़ंक्शन कई अनुवाद इकाइयों में परिभाषित किया जाएगा, इसके बारे में चिंता न करें। लिंकर को यह सुनिश्चित करने की आवश्यकता है कि सभी अनुवाद इकाइयाँ चर / फ़ंक्शन के एक ही उदाहरण का उपयोग करें।

नोट: आम तौर पर, टेम्पलेट्स inlineकी घोषणा व्यर्थ है, क्योंकि उनके पास inlineपहले से ही लिंकेज शब्दार्थ है । हालांकि, स्पष्ट विशेषज्ञता और टेम्पलेट्स की तात्कालिकता आवश्यकताinline है।


आपके प्रश्नों के विशिष्ट उत्तर:

  • मुझे C ++ में किसी फ़ंक्शन / विधि के लिए कीवर्ड 'इनलाइन' कब लिखना चाहिए?

    केवल जब आप फ़ंक्शन को हेडर में परिभाषित करना चाहते हैं। अधिक केवल तभी जब फ़ंक्शन की परिभाषा कई अनुवाद इकाइयों में दिखाई दे सकती है। हेडर फ़ाइल में छोटे (एक लाइनर के रूप में) कार्यों को परिभाषित करना एक अच्छा विचार है क्योंकि यह आपके कोड को अनुकूलित करते समय काम करने वाले को अधिक जानकारी देता है। यह संकलन समय भी बढ़ाता है।

  • C ++ में किसी फ़ंक्शन / पद्धति के लिए मुझे 'इनलाइन' कीवर्ड कब नहीं लिखना चाहिए?

    इनलाइन को न जोड़ें क्योंकि आपको लगता है कि यदि कंपाइलर इसमें प्रवेश करता है तो आपका कोड तेजी से चलेगा।

  • कंपाइलर को पता नहीं चलेगा कि फंक्शन / मेथड 'इनलाइन' कब बनाया जाएगा?

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

    जीसीसी में इनलाइनिंग को रोकने के लिए अलग से __attribute__(( noinline )), और विज़ुअल स्टूडियो में, उपयोग करें __declspec(noinline)

  • क्या कोई फर्क पड़ता है अगर कोई फ़ंक्शन / पद्धति के लिए 'इनलाइन' लिखने पर एप्लिकेशन को मल्टीथ्रेड किया जाता है?

    मल्टीथ्रेडिंग किसी भी तरह से इनलाइनिंग को प्रभावित नहीं करता है।


172
+1 इनलाइन का सर्वश्रेष्ठ विवरण मैंने ... (हमेशा के लिए) में देखा है। अब मैं आपको चीर दूंगा और इनलाइन कीवर्ड के मेरे सभी स्पष्टीकरणों में इसका उपयोग करूंगा।
मार्टिन यॉर्क

6
@Ziggy, मैं जो कहना चाह रहा था वह यह था कि कंपाइलर इनलाइनिंग और inlineकीवर्ड संबंधित नहीं हैं। आपको सही विचार मिला है। एक नियम के रूप में, यह अनुमान लगाना कि इनलाइनिंग से क्या सुधार होगा, बहुत त्रुटि प्रवण है। उस नियम का अपवाद एक लाइनर होना है।
deft_code

4
यह उत्तर मुझे थोड़ा भ्रमित करता है। आप सभी कहते हैं कि कंपाइलर इनलाइन चीजों को बेहतर तरीके से इनलाइन / सक्षम नहीं कर पा रहा है। फिर आप कहते हैं कि आपको हेडर में एक लाइनर / छोटे फ़ंक्शंस लगाने चाहिए, और कंपाइलर फ़ंक्शन परिभाषा के बिना इनलाइन कोड को नहीं कर सकता है। ये थोड़े विरोधाभासी नहीं हैं? क्यों न सिर्फ सब कुछ cpp फाइल में डाला जाए और कंपाइलर को तय करने दिया जाए?
user673679

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

8
जब भी मैं इंटरनेट के संचयी ज्ञान के बारे में कुछ पढ़ता हूं तो मुझे जॉन लॉटन के प्रसिद्ध उद्धरण के बारे में सोचना पड़ता है: सूचना युग की विडंबना यह है कि इसने बिना किसी विचार के नया सम्मान दिया है।
IInspectable

60

मैं किसी भी शेष गलतफहमी को दूर करने के लिए एक ठोस उदाहरण के साथ इस सूत्र में सभी महान उत्तरों में योगदान देना चाहता हूं।

दो स्रोत फ़ाइलों को दिया, जैसे:

  • inline111.cpp:

    #include <iostream>
    
    void bar();
    
    inline int fun() {
      return 111;
    }
    
    int main() {
      std::cout << "inline111: fun() = " << fun() << ", &fun = " << (void*) &fun;
      bar();
    }
  • inline222.cpp:

    #include <iostream>
    
    inline int fun() {
      return 222;
    }
    
    void bar() {
      std::cout << "inline222: fun() = " << fun() << ", &fun = " << (void*) &fun;
    }

  • केस ए:

    संकलन :

    g++ -std=c++11 inline111.cpp inline222.cpp

    आउटपुट :

    inline111: fun() = 111, &fun = 0x4029a0
    inline222: fun() = 111, &fun = 0x4029a0

    चर्चा :

    1. यहां तक ​​कि आपको अपने इनलाइन फ़ंक्शंस की समान परिभाषाएँ मिलनी चाहिए, C ++ कंपाइलर इसे फ़्लैग नहीं करता है अगर ऐसा नहीं है (वास्तव में, अलग-अलग संकलन के कारण इसकी जांच करने के कोई तरीके नहीं हैं)। यह सुनिश्चित करना आपका अपना कर्तव्य है!

    2. लिंकर वन डेफिनिशन नियम के बारे में शिकायत नहीं करता है , जैसा fun()कि घोषित किया गया है inline। हालाँकि, क्योंकि इनलाइन111.cppfun() संकलक द्वारा संसाधित पहली अनुवाद इकाई (जिसे वास्तव में कॉल करता है ) है, संकलक इनलाइन111 . cpp में fun()अपनी पहली कॉल-एनकाउंटर पर तत्काल हो जाता है । संकलक फैसला करती है तो नहीं विस्तार करने के लिए fun()अपने कार्यक्रम में कहीं और से अपनी कॉल पर ( जैसे से inline222.cpp ), करने के लिए कॉल fun()हमेशा अपने उदाहरण से उत्पादित से लिंक किया जाएगा inline111.cpp (करने के लिए कॉल fun()के अंदर inline222.cppउस अनुवाद इकाई में एक उदाहरण भी प्रस्तुत कर सकता है, लेकिन यह अनलंकृत रहेगा)। वास्तव में, यह समान &fun = 0x4029a0प्रिंट-आउट से स्पष्ट है ।

    3. अंत में, inlineकंपाइलर को वास्तव में वन-लाइनर का विस्तार करने के सुझाव के बावजूद fun(), यह आपके सुझाव को पूरी तरह से अनदेखा कर देता है , जो स्पष्ट है क्योंकि fun() = 111दोनों लाइनों में।


  • केस B:

    संकलन (नोटिस रिवर्स ऑर्डर) :

    g++ -std=c++11 inline222.cpp inline111.cpp

    आउटपुट :

    inline111: fun() = 222, &fun = 0x402980
    inline222: fun() = 222, &fun = 0x402980

    चर्चा :

    1. यह मामला केस ए में चर्चा की गई है ।

    2. एक महत्वपूर्ण बिंदु पर ध्यान दें, यदि आप inline222.cppfun() में वास्तविक कॉल को कमेंट करते हैं ( उदाहरण के लिए इनलाइन222cout . cpp में पूरी तरह से टिप्पणी करें ), तब, आपकी अनुवाद इकाइयों के संकलन आदेश के बावजूद, fun()पहली कॉल एनकाउंटर में तुरंत चालू हो जाएगी। inline111.cpp , केस बी के रूप में प्रिंट-आउट के परिणामस्वरूप inline111: fun() = 111, &fun = 0x402980


  • केस C:

    संकलन (नोटिस -O2) :

    g++ -std=c++11 -O2 inline222.cpp inline111.cpp

    या

    g++ -std=c++11 -O2 inline111.cpp inline222.cpp

    आउटपुट :

    inline111: fun() = 111, &fun = 0x402900
    inline222: fun() = 222, &fun = 0x402900

    चर्चा :

    1. के रूप में किया जाता है यहाँ वर्णित , -O2अनुकूलन संकलक को प्रोत्साहित करती है के लिए वास्तव में विस्तार कार्यों कि inlined जा सकता है (सूचना भी है कि -fno-inlineहै डिफ़ॉल्ट अनुकूलन विकल्प के बिना)। जैसा कि यहां की गई छाप से स्पष्ट है, fun()वास्तव में इनलाइन विस्तारित (उस विशेष अनुवाद इकाई में इसकी परिभाषा के अनुसार ) किया गया है, जिसके परिणामस्वरूप दो अलग fun() - अलग प्रिंट-आउट हैं। इसके बावजूद, अभी भी केवल एक वैश्विक रूप से जुड़ा हुआ उदाहरण है fun()(मानक द्वारा आवश्यक), जैसा कि समान &fun प्रिंट-आउट से स्पष्ट है।

8
आपका उत्तर इस बात का उदाहरण है कि भाषा ऐसे inlineकार्यों को अपरिभाषित व्यवहार क्यों बनाती है।
आर साहू

आपको उन मामलों को भी जोड़ना चाहिए जहां संकलन और लिंकिंग अलग-अलग हैं, प्रत्येक की .cppअपनी अनुवाद इकाई है। अधिमानतः, -fltoसक्षम / अक्षम के लिए मामले जोड़ें ।
syockit

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

27

टेम्प्लेट स्पेशलाइज़ेशन (यदि स्पेशलाइज़ेशन .h फ़ाइल में है) करते समय आपको अपने फ़ंक्शन को स्पष्ट रूप से इनलाइन करना होगा।


21

1) आजकल, बहुत ज्यादा कभी नहीं। यदि किसी फ़ंक्शन को इनलाइन करना एक अच्छा विचार है, तो संकलक आपकी सहायता के बिना करेगा।

2) हमेशा। # 1 देखें।

(यह दर्शाने के लिए संपादित कि आपने अपने प्रश्न को दो प्रश्नों में तोड़ दिया है ...)


हाँ। इनलाइन संकलक के लिए केवल एक संकेत है, और यह आपको अनदेखा करने के लिए स्वतंत्र है। इन दिनों कंपाइलर शायद प्रोग्रामर से बेहतर जानता है कि कौन से फंक्शन इनलाइन बेस्ट हैं।
मार्क बायर्स

1
हां, लेकिन यह कम प्रासंगिक है - किसी फ़ंक्शन को इनलाइन किए जाने के लिए, यह बॉडी एक ही संकलन इकाई (उदाहरण के लिए, हेडर में) होनी चाहिए। C कार्यक्रमों में यह कम आम है।
माइकल कोहेन

1
एक गैर-सदस्य फ़ंक्शन टेम्पलेट (उर्फ गैर-स्थिर फ़ंक्शन टेम्पलेट) को परिभाषित करने के लिए इनलाइन की आवश्यकता नहीं होती है। एक परिभाषा नियम (3.2 / 5) देखें।
deft_code

2
-1: inlineअभी भी जरूरत है, उदाहरण के लिए एक हेडर फ़ाइल में एक फ़ंक्शन को परिभाषित करने के लिए (और कई संकलन इकाइयों में इस तरह के फ़ंक्शन को इनलाइन करने के लिए आवश्यक है)।
मेलेबियस

1
@ Étienne जो कि कार्यान्वयन-विशिष्ट है। मानक के अनुसार, वन डेफिनिशन रूल है, जिसका मतलब है कि यहां यदि आप भोलेपन में फ़ंक्शन परिभाषा को कई अनुवाद इकाइयों में शामिल करते हैं, तो आपको एक त्रुटि मिलेगी। लेकिन अगर उस फ़ंक्शन में inlineस्पेसिफिकेशन्स हैं, तो इसके इंस्टेंसेस ऑटोमैटिकली लिंकर द्वारा एक में ढह जाते हैं, और ODR का उपयोग नहीं किया जाता है।
रुस्लान

12

C ++ में किसी फ़ंक्शन / पद्धति के लिए मुझे 'इनलाइन' कीवर्ड कब नहीं लिखना चाहिए?

यदि फ़ंक्शन हेडर में घोषित किया गया है और .cppफ़ाइल में परिभाषित किया गया है, तो आपको कीवर्ड नहीं लिखना चाहिए ।

कंपाइलर को पता नहीं चलेगा कि फंक्शन / मेथड 'इनलाइन' कब बनाया जाएगा?

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

क्या कोई फर्क पड़ता है अगर कोई फ़ंक्शन / पद्धति के लिए 'इनलाइन' लिखने पर एप्लिकेशन को मल्टीथ्रेड किया जाता है?

नहीं, इससे कोई फर्क नहीं पड़ता।


ऐसे मामले हैं जहां इनकैप फ़ाइल में इनलाइन का उपयोग करना उचित है। उदाहरण के लिए कोड को अनुकूलन लागू करना जो पूरी तरह से विशिष्ट कार्यान्वयन है।
रॉबिन डेविस

@RobinDavies अपडेटेड उत्तर। ऐसा लगता है कि आप गलत समझ रहे हैं कि मैं क्या लिखना चाहता था।
जोहान्स शहाब -

5
  • कंपाइलर को पता नहीं चलेगा कि फंक्शन / मेथड 'इनलाइन' कब बनाया जाएगा?

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

चारों ओर कई सूत्र पढ़ने के बाद मैंने जिज्ञासा से बाहर की कोशिश की कि मैं अभी काम कर रहा हूं कोड पर इनलाइन के प्रभाव और मुझे जीसीसी के लिए औसत दर्जे का स्पीडअप मिला और इंटेल कंपाइलर के लिए कोई गति नहीं हुई।

(अधिक विवरण: वर्ग के बाहर परिभाषित कुछ महत्वपूर्ण कार्यों के साथ गणित सिमुलेशन, GCC 4.6.3 (g ++ -O3), ICC 13.1.0 (icpc -O3), महत्वपूर्ण बिंदुओं के लिए इनलाइन जोड़ना GCC कोड के साथ + 6% स्पीडअप)।

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


6
मैं आपके दावों का समर्थन करने के लिए और अधिक सबूत देखना चाहता हूं। कृपया कोड प्रदान करें जो आप परीक्षण कर रहे हैं और साथ ही इनलाइन कीवर्ड के साथ और असेंबलर आउटपुट के साथ परीक्षण कर रहे हैं। कोई भी चीज़ आपको प्रदर्शन लाभ दे सकती है।
void.pointer

1
अंत में कोई ऐसा व्यक्ति जो दूसरों के कहे अनुसार को दोहराता नहीं है, लेकिन वास्तव में उन बयानों को सत्यापित करता है। Gcc वास्तव में अभी भी इनलाइन कीवर्ड को एक संकेत के रूप में मानता है (मुझे लगता है कि क्लैंग इसे पूरी तरह से अनदेखा करता है)।
माइकएम

@ void.pointer: यह विश्वास करना इतना कठिन क्यों है? यदि ऑप्टिमाइज़र पहले से ही परिपूर्ण थे, तो नए संस्करण प्रोग्राम के प्रदर्शन में सुधार नहीं कर सकते थे। लेकिन वे नियमित रूप से करते हैं।
माइकएम

3

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

कंपाइलर आमतौर पर इस तरह की चीजों का पता लगाने + का अनुकूलन करने का एक अच्छा काम करेगा।


7
समस्या यह है कि C ++ में inlineएक शब्दार्थ अंतर है (जैसे कि कई परिभाषाओं का इलाज किया जाता है), जो कुछ मामलों में महत्वपूर्ण है (जैसे टेम्पलेट)।
पावेल मिनेव

4
इनलाइन का उपयोग उन मामलों को हल करने के लिए किया जाता है जहां एक प्रतीक की कई परिभाषाएं होती हैं। हालाँकि टेम्प्लेट पहले से ही भाषा द्वारा संभाले जाते हैं। एक अपवाद एक विशेष टेम्प्लेट फ़ंक्शन है जिसमें अब कोई टेम्पलेट पैरामेट्स नहीं है (टेम्पलेट <>)। इन्हें टेम्प्लेट की तुलना में अधिक कार्य किया जाता है और इसलिए लिंक करने के लिए इनलाइन कीवर्ड की आवश्यकता होती है।
deft_code

2

अनुकूलन सक्षम किए बिना संकलित करने पर डिफ़ॉल्ट रूप से gcc किसी भी फ़ंक्शन को इनलाइन नहीं करता है। मैं दृश्य स्टूडियो के बारे में नहीं जानता - deft_code

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


1
सक्षम / दीवार के बारे में बताया जा सकता है कि कौन से कार्य जहां इनलाइन के रूप में चिह्नित किए गए हैं, लेकिन वास्तव में
इनबिल्ट

0

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


0

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

(लेकिन देखें कि क्या लिंक टाइम ऑप्टिमाइज़ेशन का उपयोग न करने का कोई कारण है? )


0

C ++ इनलाइन, C इनलाइन से बिलकुल अलग है।

#include <iostream>
extern inline int i[];
int i [5];
struct c {
  int function (){return 1;} //implicitly inline
  static inline int j = 3; //explicitly inline
};
int main() {
  c j;
  std::cout << i;
}

inlineअपने आप ही संकलक, कोडांतरक और लिंकर को प्रभावित करता है। यह संकलक के लिए एक निर्देश है जिसमें कहा गया है कि केवल इस फ़ंक्शन / डेटा के लिए एक प्रतीक का उपयोग करें यदि यह अनुवाद इकाई में उपयोग किया जाता है, और यदि यह है, तो कक्षा विधियों की तरह, कोड में उन्हें स्टोर करने के लिए कोडांतरक को बताएं.section .text.c::function(),"axG",@progbits,c::function(),comdat या.section .bss.i,"awG",@nobits,i,comdat डेटा के ।

यह इस प्रकार है .section name, "flags"MG, @type, entsize, GroupName[, linkage]। उदाहरण के लिए, अनुभाग नाम है .text.c::function()axGइसका मतलब यह है कि यह खंड आवंटन योग्य है, निष्पादन योग्य है और एक समूह में एक समूह का नाम निर्दिष्ट किया जाएगा (और कोई एम झंडा नहीं है, इसलिए कोई entsize निर्दिष्ट नहीं किया जाएगा); @progbitsइसका मतलब है कि अनुभाग में डेटा है और रिक्त नहीं है; c::function()समूह का नाम और समूह हैcomdatलिंकेज का अर्थ है कि सभी ऑब्जेक्ट फ़ाइलों में, इस समूह के नाम के साथ काम करने वाले सभी वर्गों को कॉमडेट के साथ टैग किया गया, अंतिम निष्पादन योग्य से हटा दिया जाएगा 1 को छोड़कर। संकलक यह सुनिश्चित करता है कि अनुवाद इकाई में केवल एक ही परिभाषा है और फिर कोड डालने के लिए कोडांतरक से कहता है यह ऑब्जेक्ट फ़ाइल में अपने समूह में (1 समूह में 1 खंड) और फिर लिंकर यह सुनिश्चित करेगा कि यदि किसी भी ऑब्जेक्ट फ़ाइलों में समान नाम वाला कोई समूह है, तो केवल अंतिम में एक को शामिल करें। exe। के बीच का अंतर inlineऔर उपयोग नहींinlineअब कोडांतरक को दिखाई दे रहा है और परिणामस्वरूप लिंकर, क्योंकि यह नियमित में संग्रहीत नहीं है .dataया.text उनके निर्देशन के कारण कोडांतरक द्वारा आदि ।

static inlineएक कक्षा में इसका मतलब है कि यह एक प्रकार की परिभाषा है और घोषणा नहीं है (स्थिर सदस्य को कक्षा में परिभाषित करने की अनुमति देता है) और इसे इनलाइन बनाता है; यह अब ऊपर जैसा व्यवहार करता है।

static inlineफ़ाइल स्कोप पर केवल कंपाइलर को प्रभावित करता है। यह संकलक के लिए इसका अर्थ है: केवल इस फ़ंक्शन / डेटा के लिए एक प्रतीक का उत्सर्जन करें यदि इसका अनुवाद इकाई में उपयोग किया जाता है और ऐसा एक नियमित स्थैतिक प्रतीक (स्टोर in.text /.data बिना .globl निर्देश के) के रूप में करें। कोडांतरक के बीच अब कोई अंतर नहीं है staticऔरstatic inline

extern inlineएक घोषणा है जिसका अर्थ है कि आपको अनुवाद इकाई में इस प्रतीक को परिभाषित करना चाहिए या संकलक त्रुटि फेंकना चाहिए; अगर यह तो परिभाषित किया है एक नियमित रूप से मानते हैं inlineऔर कोडांतरक और संयोजक के लिए वहाँ के बीच कोई अंतर हो जाएगा extern inlineऔर inlineहै, तो यह केवल एक संकलक गार्ड है।

extern inline int i[];
extern int i[]; //allowed repetition of declaration with incomplete type, inherits inline property
extern int i[5]; //declaration now has complete type
extern int i[5]; //allowed redeclaration if it is the same complete type or has not yet been completed
extern int i[6]; //error, redeclaration with different complete type
int i[5]; //definition, must have complete type and same complete type as the declaration if there is a declaration with a complete type

त्रुटि पंक्ति के बिना ऊपर का पूरा हिस्सा ढह जाता है inline int i[5]। जाहिर है अगर आपने कियाextern inline int i[] = {5}; उसके बादextern असाइनमेंट के माध्यम से स्पष्ट परिभाषा के कारण नजरअंदाज कर दिया जाएगा।

inlineएक नाम स्थान पर, इसे और इसे देखें


0

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

कब इस्तेमाल करें:

  • प्रदर्शन में सुधार करने के लिए
  • ओवरहेड कॉल को कम करने के लिए।
  • जैसा कि यह संकलक से केवल एक अनुरोध है, कुछ कार्य * बड़े कार्यों को इनलाइन नहीं किया जाएगा
    • कई सशर्त तर्क वाले कार्य
    • पुनरावर्ती कोड और कोड के साथ छोरों आदि।

-1

कोड विकसित और डिबगिंग inlineकरते समय , बाहर निकलें। यह डीबगिंग को जटिल करता है।

उन्हें जोड़ने का मुख्य कारण उत्पन्न कोड को अनुकूलित करने में मदद करना है। आमतौर पर यह ट्रेड गति के लिए कोड स्थान को बढ़ाता है, लेकिन कभी-कभी inlineकोड स्थान और निष्पादन समय दोनों को बचाता है।

एल्गोरिथ्म पूरा होने से पहले प्रदर्शन अनुकूलन के बारे में इस तरह के विचार का विस्तार करना समयपूर्व अनुकूलन है


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

3
अनुकूलन सक्षम किए बिना संकलित करने पर डिफ़ॉल्ट रूप से gcc किसी भी फ़ंक्शन को इनलाइन नहीं करता है। मैं दृश्य स्टूडियो के बारे में नहीं जानता
deft_code

मैंने एक विशाल g ++ प्रोजेक्ट पर काम किया, जिसमें डीबगिंग सक्षम थी। हो सकता है कि अन्य विकल्पों ने इसे रोका हो, लेकिन inlineफ़ंक्शन इनबिल्ड थे। उनमें एक सार्थक विराम बिंदु स्थापित करना असंभव था।
23:18 बजे wallyk

2
डिबगिंग को सक्षम करना जीसीसी में इनलाइनिंग को रोकना नहीं है। यदि कोई अनुकूलन जहां -O1 या अधिक सक्षम है, तो gcc सबसे स्पष्ट मामलों को इनलाइन करने का प्रयास करेगा। परंपरागत रूप से GDB का ब्रेकपॉइंट और कंस्ट्रक्टर्स के साथ विशेष रूप से इनलाइन कंस्ट्रक्टर्स के लिए एक कठिन समय रहा है। लेकिन, यह हाल के संस्करणों (कम से कम 6.7, शायद जल्दी) में तय किया गया है।
deft_code

2
जोड़ना inlineएक आधुनिक संकलक पर कोड को बेहतर बनाने के लिए कुछ नहीं करेगा, जो यह पता लगा सकता है कि क्या इनलाइन है या नहीं।
डेविड थॉर्नले

-1

जब एक इनलाइन होना चाहिए:

1. जब कोई ऐसा कार्य हो रहा हो, जब फंक्शन को पैरामीटर पासिंग, कंट्रोल ट्रांसफर, कंट्रोल रिटर्न इत्यादि कहा जाता है।

2. फ़ंक्शन छोटा होना चाहिए, अक्सर कहा जाता है और इनलाइन बनाना 80-20 के नियम के अनुसार वास्तव में फायदेमंद है, उन फ़ंक्शन को इनलाइन बनाने का प्रयास करें, जो कार्यक्रम के प्रदर्शन पर बड़ा प्रभाव डालते हैं।

जैसा कि हम जानते हैं कि इनलाइन केवल रजिस्टर करने के लिए संकलक के लिए एक अनुरोध है और यह आपको ऑब्जेक्ट कोड आकार में खर्च होगा।


"इनलाइन सिर्फ रजिस्टर करने के लिए संकलक के लिए एक अनुरोध है" वे समान हैं क्योंकि न तो अनुरोध हैं और न ही अनुकूलन के साथ कुछ करना है। inlineएक अनुकूलन संकेत के रूप में अपनी स्थिति खो दी है, और अधिकांश संकलक इसका उपयोग केवल कई परिभाषाओं के लिए भत्ते बनाने के लिए करते हैं - जैसा कि उन्हें चाहिए IMO। इसलिए, C ++ 11 के बाद से, register'मैं कंपाइलर को कैसे ऑप्टिमाइज़ करना है, से बेहतर जानता हूं' के अपने पूर्व अर्थ के लिए पूरी तरह से हटा दिया गया है: यह अब केवल एक मौजूदा शब्द है जिसका कोई वर्तमान अर्थ नहीं है।
अंडरस्कोर_ड

@underscore_d: Gcc अभी भी inlineकुछ हद तक सुनता है ।
माइकएमबी

-1

C ++ इनलाइन फ़ंक्शन शक्तिशाली अवधारणा है जिसे आमतौर पर कक्षाओं के साथ उपयोग किया जाता है। यदि कोई फ़ंक्शन इनलाइन है, तो कंपाइलर प्रत्येक बिंदु पर उस फ़ंक्शन के कोड की एक कॉपी रखता है जहां फ़ंक्शन को संकलन समय पर बुलाया जाता है।

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

किसी फ़ंक्शन को इनलाइन करने के लिए, फ़ंक्शन नाम से पहले कीवर्ड इनलाइन रखें और फ़ंक्शन को कॉल करने से पहले फ़ंक्शन को परिभाषित करें। कंपाइलर इनलाइन क्वालिफायर को अनदेखा कर सकता है यदि परिभाषित फ़ंक्शन एक लाइन से अधिक है।

एक वर्ग परिभाषा में एक फ़ंक्शन परिभाषा एक इनलाइन फ़ंक्शन परिभाषा है, यहां तक ​​कि इनलाइन विनिर्देशक के उपयोग के बिना भी।

निम्नलिखित एक उदाहरण है, जो अधिकतम दो संख्याओं को वापस करने के लिए इनलाइन फ़ंक्शन का उपयोग करता है

#include <iostream>

using namespace std;

inline int Max(int x, int y) { return (x > y)? x : y; }

// Main function for the program
int main() {
   cout << "Max (100,1010): " << Max(100,1010) << endl;

   return 0;
}

अधिक जानकारी के लिए यहाँ देखें ।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.