c++ inline - इनलाइन फ़ंक्शंस-वे इनलाइन कीवर्ड के विज़न-ए-विज़ क्या हैं?




function hindi (4)

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

इनलाइन फ़ंक्शन या इनलाइन वैरिएबल (C ++ 17 के बाद) एक फ़ंक्शन या वैरिएबल है (C ++ 17 के बाद से) निम्न गुणों के साथ:

1) कार्यक्रम में इनलाइन फ़ंक्शन या चर (C ++ 17 के बाद से) की एक से अधिक परिभाषा हो सकती है जब तक कि प्रत्येक परिभाषा एक अलग अनुवाद इकाई में दिखाई देती है। उदाहरण के लिए, इनलाइन फ़ंक्शन या इनलाइन वैरिएबल (C ++ 17 के बाद) को एक हेडर फ़ाइल में परिभाषित किया जा सकता है जो कई मल्टीपल फ़ाइलों में शामिल है।

यहां मेरे पास पहले से ही समझने की समस्याएं हैं, घोषणा नए पहचानकर्ताओं की विशिष्टता है

void func(void);

जबकि एक परिभाषा शरीर सहित वास्तविक कार्यान्वयन है

void func(void) {
  //some code...
}

बिंदु 1) का अर्थ है कि जब तक मैं अलग-अलग अनुवाद इकाइयों में अलग-अलग कार्यान्वयन दे सकता हूं (यानी प्रति स्रोत ई प्रति स्रोत फ़ाइलें एक कार्यान्वयन), लेकिन मैं उस मामले में हैरान हूं जब मेरे पास स्रोत फ़ाइल source.cc है। func और एक हेडर फाइल के लिए डिक्लेरेशन की एक और घोषणा के साथ एक ट्रांसलेशन func ट्रांसलेशन यूनिट युग्म source.cc+header.h हेडर source.cc+header.h और ऐसे मामले में दो बार की गई func को कोई मतलब नहीं होता है, क्या यह सही है?

2) एक इनलाइन फ़ंक्शन या वेरिएबल की परिभाषा (C ++ 17 के बाद) अनुवाद इकाई में मौजूद होनी चाहिए, जहां यह एक्सेस की जाती है (एक्सेस के बिंदु से पहले जरूरी नहीं)।

यह सामान्य मामला है जहां मैं घोषणा से अलग करता हूं, हेडर फ़ाइल में पहला, दूसरा स्रोत फ़ाइल में है, अगर मुझे फ़ंक्शन का उपयोग करने की आवश्यकता है, तो मुझे केवल हेडर शामिल करना होगा? लिंकिंग चरण के दौरान स्रोत द्वारा पहुंच बिंदु प्रदान किया जाएगा, सही?

3) बाह्य लिंकेज (जैसे कि स्थिर घोषित नहीं किया गया) के साथ एक इनलाइन फ़ंक्शन या चर (चूंकि सी ++ 17) में निम्नलिखित अतिरिक्त गुण हैं: 1) इसे प्रत्येक अनुवाद इकाई में इनलाइन घोषित किया जाना चाहिए। 2) हर अनुवाद इकाई में इसका एक ही पता होता है।

क्या आप इसका एक सरल उदाहरण प्रदान कर सकते हैं? मैं इस तरह के एक मामले की व्यावहारिक तस्वीर नहीं कर सकता। मामला 3) बताता है कि जब तक फ़ंक्शन को स्थिर घोषित नहीं किया जाता है तब तक कीवर्ड inline अनिवार्य है।

क्या मैंने जो कुछ कहा वह सब सही है?

व्यवहार में एक फ़ंक्शन इनलाइन होना चाहिए, जब ऐसा फ़ंक्शन बहुत छोटा होता है, लेकिन हमेशा कंपाइलर इनलाइन के रूप में घोषित फ़ंक्शन को इनलाइन नहीं करता है, उदाहरण के लिए यदि इसमें लूप्स अंदर या पुनरावर्ती है (प्रभावी C ++ स्टेट्स तो)। सामान्य तौर पर यह संकलक पर निर्भर है, मुझे आश्चर्य है कि अब ...

मान लें कि मेरे पास दो कार्य हैं पहला पहला स्व-निहित है (यह आंतरिक रूप से किसी अन्य फ़ंक्शन को कॉल नहीं करता है), दूसरा एक कॉल पहले वाला है (आप मान सकते हैं कि वे तर्क के लिए दोनों 10 लाइनें हैं)। क्या इन दोनों को इनलाइन घोषित किया जाना चाहिए? क्या उन्हें हेडर फ़ाइल में घोषित किया जाना चाहिए? या क्या मुझे हेडर फ़ाइल और स्रोत फ़ाइल में कार्यान्वयन की परिभाषा अलग-अलग करनी चाहिए? क्या बेहतर होगा?

1 संपादित करें :

यदि मैं उदाहरण के लिए संबंधित विधानसभा कोड विश्लेषण के साथ काम करता हूं, तो उत्तर में से एक का पालन करना बेहतर है।

मैंने पिछला कोड हटा दिया क्योंकि यह अर्थहीन था ( -O3 फ्लैग ऑप्टिमाइज़ेशन सेट नहीं था)।

मैं फिर से शुरू करता हूं ... मेरे पास 5 फाइलें src.cc , src1.cc , src2.cc , src2.cc और main.cc प्रत्येक अनुवाद इकाई के लिए संबंधित असेंबली कोड पोस्ट किया गया है।

मैंने तीन अलग-अलग तरीकों से ऐसी फ़ाइलों में हेरफेर किया है और बाद में उत्पन्न विधानसभा कोड का अवलोकन किया, इससे मुझे यह समझने में मदद मिली कि इनलाइन कीवर्ड कैसे काम करता है।

उदाहरण 1:

header.h

#ifndef HEADER_H_
#define HEADER_H_

int func(int a, int b);
int test_1();
int test_2();

#endif /* HEADER_H_ */

src.cc

#include "header.h"

int func(int a, int b)
{
   return a + b;
}

src1.cc

#include "header.h"

int test_1()
{
   int a, b, c;
   a = 3;
   b = 7;
   c = func(a, b);
   return c;
}

src2.cc

#include "header.h"

int test_2()
{
   int a, b, c;
   a = 7;
   b = 8;
   c = func(a, b);
   return c;
}

main.cc

int main(int argc, char** argv)
{
   test_1();
   test_2();
   test_1();
   test_2();
}

विधानसभा 1:

src.s

GAS LISTING /tmp/cc0j97WY.s             page 1


   1                    .file   "src.cc"
   2                    .text
   3                    .align 2
   4                    .p2align 4,,15
   5                .globl _Z4funcii
   6                    .type   _Z4funcii, @function
   7                _Z4funcii:
   8                .LFB2:
   9 0000 8D043E        leal    (%rsi,%rdi), %eax
  10 0003 C3            ret
  11                .LFE2:
  12                    .size   _Z4funcii, .-_Z4funcii
  13                .globl __gxx_personality_v0
  14                    .section    .eh_frame,"a",@progbits
  15                .Lframe1:
  16 0000 1C000000      .long   .LECIE1-.LSCIE1
  17                .LSCIE1:
  18 0004 00000000      .long   0x0
  19 0008 01            .byte   0x1
  20 0009 7A505200      .string "zPR"
  21 000d 01            .uleb128 0x1
  22 000e 78            .sleb128 -8
  23 000f 10            .byte   0x10
  24 0010 06            .uleb128 0x6
  25 0011 03            .byte   0x3
  26 0012 00000000      .long   __gxx_personality_v0
  27 0016 03            .byte   0x3
  28 0017 0C            .byte   0xc
  29 0018 07            .uleb128 0x7
  30 0019 08            .uleb128 0x8
  31 001a 90            .byte   0x90
  32 001b 01            .uleb128 0x1
  33 001c 00000000      .align 8
  34                .LECIE1:
  35                .LSFDE1:
  36 0020 14000000      .long   .LEFDE1-.LASFDE1
  37                .LASFDE1:
  38 0024 24000000      .long   .LASFDE1-.Lframe1
  39 0028 00000000      .long   .LFB2
  40 002c 04000000      .long   .LFE2-.LFB2
  41 0030 00            .uleb128 0x0
  42 0031 00000000      .align 8
  42      000000
  43                .LEFDE1:
  44                    .ident  "GCC: (GNU) 4.1.2 20080704 (Red Hat 4.1.2-54)"
  45                    .section    .note.GNU-stack,"",@progbits

src1.s

GAS LISTING /tmp/cchSilt1.s             page 1


   1                    .file   "src1.cc"
   2                    .text
   3                    .align 2
   4                    .p2align 4,,15
   5                .globl _Z6test_1v
   6                    .type   _Z6test_1v, @function
   7                _Z6test_1v:
   8                .LFB2:
   9 0000 BE070000      movl    $7, %esi
   9      00
  10 0005 BF030000      movl    $3, %edi
  10      00
  11 000a E9000000      jmp _Z4funcii
  11      00
  12                .LFE2:
  13                    .size   _Z6test_1v, .-_Z6test_1v
  14                .globl __gxx_personality_v0
  15                    .section    .eh_frame,"a",@progbits
  16                .Lframe1:
  17 0000 1C000000      .long   .LECIE1-.LSCIE1
  18                .LSCIE1:
  19 0004 00000000      .long   0x0
  20 0008 01            .byte   0x1
  21 0009 7A505200      .string "zPR"
  22 000d 01            .uleb128 0x1
  23 000e 78            .sleb128 -8
  24 000f 10            .byte   0x10
  25 0010 06            .uleb128 0x6
  26 0011 03            .byte   0x3
  27 0012 00000000      .long   __gxx_personality_v0
  28 0016 03            .byte   0x3
  29 0017 0C            .byte   0xc
  30 0018 07            .uleb128 0x7
  31 0019 08            .uleb128 0x8
  32 001a 90            .byte   0x90
  33 001b 01            .uleb128 0x1
  34 001c 00000000      .align 8
  35                .LECIE1:
  36                .LSFDE1:
  37 0020 14000000      .long   .LEFDE1-.LASFDE1
  38                .LASFDE1:
  39 0024 24000000      .long   .LASFDE1-.Lframe1
  40 0028 00000000      .long   .LFB2
  41 002c 0F000000      .long   .LFE2-.LFB2
  42 0030 00            .uleb128 0x0
  43 0031 00000000      .align 8
  43      000000
  44                .LEFDE1:
  45                    .ident  "GCC: (GNU) 4.1.2 20080704 (Red Hat 4.1.2-54)"
  46                    .section    .note.GNU-stack,"",@progbits

src2.s

GAS LISTING /tmp/cc2JMtt3.s             page 1


   1                    .file   "src2.cc"
   2                    .text
   3                    .align 2
   4                    .p2align 4,,15
   5                .globl _Z6test_2v
   6                    .type   _Z6test_2v, @function
   7                _Z6test_2v:
   8                .LFB2:
   9 0000 BE080000      movl    $8, %esi
   9      00
  10 0005 BF070000      movl    $7, %edi
  10      00
  11 000a E9000000      jmp _Z4funcii
  11      00
  12                .LFE2:
  13                    .size   _Z6test_2v, .-_Z6test_2v
  14                .globl __gxx_personality_v0
  15                    .section    .eh_frame,"a",@progbits
  16                .Lframe1:
  17 0000 1C000000      .long   .LECIE1-.LSCIE1
  18                .LSCIE1:
  19 0004 00000000      .long   0x0
  20 0008 01            .byte   0x1
  21 0009 7A505200      .string "zPR"
  22 000d 01            .uleb128 0x1
  23 000e 78            .sleb128 -8
  24 000f 10            .byte   0x10
  25 0010 06            .uleb128 0x6
  26 0011 03            .byte   0x3
  27 0012 00000000      .long   __gxx_personality_v0
  28 0016 03            .byte   0x3
  29 0017 0C            .byte   0xc
  30 0018 07            .uleb128 0x7
  31 0019 08            .uleb128 0x8
  32 001a 90            .byte   0x90
  33 001b 01            .uleb128 0x1
  34 001c 00000000      .align 8
  35                .LECIE1:
  36                .LSFDE1:
  37 0020 14000000      .long   .LEFDE1-.LASFDE1
  38                .LASFDE1:
  39 0024 24000000      .long   .LASFDE1-.Lframe1
  40 0028 00000000      .long   .LFB2
  41 002c 0F000000      .long   .LFE2-.LFB2
  42 0030 00            .uleb128 0x0
  43 0031 00000000      .align 8
  43      000000
  44                .LEFDE1:
  45                    .ident  "GCC: (GNU) 4.1.2 20080704 (Red Hat 4.1.2-54)"
  46                    .section    .note.GNU-stack,"",@progbits

main.s

GAS LISTING /tmp/cc5CfYBW.s             page 1


   1                    .file   "main.cc"
   2                    .text
   3                    .align 2
   4                    .p2align 4,,15
   5                .globl main
   6                    .type   main, @function
   7                main:
   8                .LFB2:
   9 0000 4883EC08      subq    $8, %rsp
  10                .LCFI0:
  11 0004 E8000000      call    _Z6test_1v
  11      00
  12 0009 E8000000      call    _Z6test_2v
  12      00
  13 000e E8000000      call    _Z6test_1v
  13      00
  14                    .p2align 4,,5
  15 0013 E8000000      call    _Z6test_2v
  15      00
  16 0018 31C0          xorl    %eax, %eax
  17 001a 4883C408      addq    $8, %rsp
  18                    .p2align 4,,1
  19 001e C3            ret
  20                .LFE2:
  21                    .size   main, .-main
  22                .globl __gxx_personality_v0
  23                    .section    .eh_frame,"a",@progbits
  24                .Lframe1:
  25 0000 1C000000      .long   .LECIE1-.LSCIE1
  26                .LSCIE1:
  27 0004 00000000      .long   0x0
  28 0008 01            .byte   0x1
  29 0009 7A505200      .string "zPR"
  30 000d 01            .uleb128 0x1
  31 000e 78            .sleb128 -8
  32 000f 10            .byte   0x10
  33 0010 06            .uleb128 0x6
  34 0011 03            .byte   0x3
  35 0012 00000000      .long   __gxx_personality_v0
  36 0016 03            .byte   0x3
  37 0017 0C            .byte   0xc
  38 0018 07            .uleb128 0x7
  39 0019 08            .uleb128 0x8
  40 001a 90            .byte   0x90
  41 001b 01            .uleb128 0x1
  42 001c 00000000      .align 8
  43                .LECIE1:
  44                .LSFDE1:
  45 0020 14000000      .long   .LEFDE1-.LASFDE1
  46                .LASFDE1:
  47 0024 24000000      .long   .LASFDE1-.Lframe1
  48 0028 00000000      .long   .LFB2
  49 002c 1F000000      .long   .LFE2-.LFB2
  50 0030 00            .uleb128 0x0
  51 0031 44            .byte   0x4
  52                    .long   .LCFI0-.LFB2
  53 0032 0E            .byte   0xe
GAS LISTING /tmp/cc5CfYBW.s             page 2


  54 0033 10            .uleb128 0x10
  55 0034 00000000      .align 8
  56                .LEFDE1:
  57                    .ident  "GCC: (GNU) 4.1.2 20080704 (Red Hat 4.1.2-54)"
  58                    .section    .note.GNU-stack,"",@progbits

उदाहरण 2:

header.h

#ifndef HEADER_H_
#define HEADER_H_

inline int func(int a, int b)
{
   return a + b;
}
int test_1();
int test_2();

#endif /* HEADER_H_ */

src.cc

#include "header.h"

/*
int func(int a, int b)
{
   return a + b;
}*/

src1.cc

#include "header.h"

int test_1()
{
   int a, b, c;
   a = 3;
   b = 7;
   c = func(a, b);
   return c;
}

src2.cc

#include "header.h"

int test_2()
{
   int a, b, c;
   a = 7;
   b = 8;
   c = func(a, b);
   return c;
}

main.cc

int main(int argc, char** argv)
{
   test_1();
   test_2();
   test_1();
   test_2();
}

विधानसभा 2:

src.s

GAS LISTING /tmp/cczLx8os.s             page 1


   1                    .file   "src.cc"
   2                    .ident  "GCC: (GNU) 4.1.2 20080704 (Red Hat 4.1.2-54)"
   3                    .section    .note.GNU-stack,"",@progbits

src1.s

GAS LISTING /tmp/ccMFMy9s.s             page 1


   1                    .file   "src1.cc"
   2                    .text
   3                    .align 2
   4                    .p2align 4,,15
   5                .globl _Z6test_1v
   6                    .type   _Z6test_1v, @function
   7                _Z6test_1v:
   8                .LFB3:
   9 0000 B80A0000      movl    $10, %eax
   9      00
  10 0005 C3            ret
  11                .LFE3:
  12                    .size   _Z6test_1v, .-_Z6test_1v
  13                .globl __gxx_personality_v0
  14                    .section    .eh_frame,"a",@progbits
  15                .Lframe1:
  16 0000 1C000000      .long   .LECIE1-.LSCIE1
  17                .LSCIE1:
  18 0004 00000000      .long   0x0
  19 0008 01            .byte   0x1
  20 0009 7A505200      .string "zPR"
  21 000d 01            .uleb128 0x1
  22 000e 78            .sleb128 -8
  23 000f 10            .byte   0x10
  24 0010 06            .uleb128 0x6
  25 0011 03            .byte   0x3
  26 0012 00000000      .long   __gxx_personality_v0
  27 0016 03            .byte   0x3
  28 0017 0C            .byte   0xc
  29 0018 07            .uleb128 0x7
  30 0019 08            .uleb128 0x8
  31 001a 90            .byte   0x90
  32 001b 01            .uleb128 0x1
  33 001c 00000000      .align 8
  34                .LECIE1:
  35                .LSFDE1:
  36 0020 14000000      .long   .LEFDE1-.LASFDE1
  37                .LASFDE1:
  38 0024 24000000      .long   .LASFDE1-.Lframe1
  39 0028 00000000      .long   .LFB3
  40 002c 06000000      .long   .LFE3-.LFB3
  41 0030 00            .uleb128 0x0
  42 0031 00000000      .align 8
  42      000000
  43                .LEFDE1:
  44                    .ident  "GCC: (GNU) 4.1.2 20080704 (Red Hat 4.1.2-54)"
  45                    .section    .note.GNU-stack,"",@progbits

src2.s

GAS LISTING /tmp/ccNXXmLv.s             page 1


   1                    .file   "src2.cc"
   2                    .text
   3                    .align 2
   4                    .p2align 4,,15
   5                .globl _Z6test_2v
   6                    .type   _Z6test_2v, @function
   7                _Z6test_2v:
   8                .LFB3:
   9 0000 B80F0000      movl    $15, %eax
   9      00
  10 0005 C3            ret
  11                .LFE3:
  12                    .size   _Z6test_2v, .-_Z6test_2v
  13                .globl __gxx_personality_v0
  14                    .section    .eh_frame,"a",@progbits
  15                .Lframe1:
  16 0000 1C000000      .long   .LECIE1-.LSCIE1
  17                .LSCIE1:
  18 0004 00000000      .long   0x0
  19 0008 01            .byte   0x1
  20 0009 7A505200      .string "zPR"
  21 000d 01            .uleb128 0x1
  22 000e 78            .sleb128 -8
  23 000f 10            .byte   0x10
  24 0010 06            .uleb128 0x6
  25 0011 03            .byte   0x3
  26 0012 00000000      .long   __gxx_personality_v0
  27 0016 03            .byte   0x3
  28 0017 0C            .byte   0xc
  29 0018 07            .uleb128 0x7
  30 0019 08            .uleb128 0x8
  31 001a 90            .byte   0x90
  32 001b 01            .uleb128 0x1
  33 001c 00000000      .align 8
  34                .LECIE1:
  35                .LSFDE1:
  36 0020 14000000      .long   .LEFDE1-.LASFDE1
  37                .LASFDE1:
  38 0024 24000000      .long   .LASFDE1-.Lframe1
  39 0028 00000000      .long   .LFB3
  40 002c 06000000      .long   .LFE3-.LFB3
  41 0030 00            .uleb128 0x0
  42 0031 00000000      .align 8
  42      000000
  43                .LEFDE1:
  44                    .ident  "GCC: (GNU) 4.1.2 20080704 (Red Hat 4.1.2-54)"
  45                    .section    .note.GNU-stack,"",@progbits

main.s

GAS LISTING /tmp/cc2cc5rp.s             page 1


   1                    .file   "main.cc"
   2                    .text
   3                    .align 2
   4                    .p2align 4,,15
   5                .globl main
   6                    .type   main, @function
   7                main:
   8                .LFB3:
   9 0000 4883EC08      subq    $8, %rsp
  10                .LCFI0:
  11 0004 E8000000      call    _Z6test_1v
  11      00
  12 0009 E8000000      call    _Z6test_2v
  12      00
  13 000e E8000000      call    _Z6test_1v
  13      00
  14                    .p2align 4,,5
  15 0013 E8000000      call    _Z6test_2v
  15      00
  16 0018 31C0          xorl    %eax, %eax
  17 001a 4883C408      addq    $8, %rsp
  18                    .p2align 4,,1
  19 001e C3            ret
  20                .LFE3:
  21                    .size   main, .-main
  22                .globl __gxx_personality_v0
  23                    .section    .eh_frame,"a",@progbits
  24                .Lframe1:
  25 0000 1C000000      .long   .LECIE1-.LSCIE1
  26                .LSCIE1:
  27 0004 00000000      .long   0x0
  28 0008 01            .byte   0x1
  29 0009 7A505200      .string "zPR"
  30 000d 01            .uleb128 0x1
  31 000e 78            .sleb128 -8
  32 000f 10            .byte   0x10
  33 0010 06            .uleb128 0x6
  34 0011 03            .byte   0x3
  35 0012 00000000      .long   __gxx_personality_v0
  36 0016 03            .byte   0x3
  37 0017 0C            .byte   0xc
  38 0018 07            .uleb128 0x7
  39 0019 08            .uleb128 0x8
  40 001a 90            .byte   0x90
  41 001b 01            .uleb128 0x1
  42 001c 00000000      .align 8
  43                .LECIE1:
  44                .LSFDE1:
  45 0020 14000000      .long   .LEFDE1-.LASFDE1
  46                .LASFDE1:
  47 0024 24000000      .long   .LASFDE1-.Lframe1
  48 0028 00000000      .long   .LFB3
  49 002c 1F000000      .long   .LFE3-.LFB3
  50 0030 00            .uleb128 0x0
  51 0031 44            .byte   0x4
  52                    .long   .LCFI0-.LFB3
  53 0032 0E            .byte   0xe
GAS LISTING /tmp/cc2cc5rp.s             page 2


  54 0033 10            .uleb128 0x10
  55 0034 00000000      .align 8
  56                .LEFDE1:
  57                    .ident  "GCC: (GNU) 4.1.2 20080704 (Red Hat 4.1.2-54)"
  58                    .section    .note.GNU-stack,"",@progbits

उदाहरण 3:

header.h

#ifndef HEADER_H_
#define HEADER_H_

inline int func(int a, int b)
{
   return a + b;
}
inline int test_1()
{
   int a, b, c;
   a = 3;
   b = 7;
   c = func(a, b);
   return c;
}
inline int test_2()
{
   int a, b, c;
   a = 7;
   b = 8;
   c = func(a, b);
   return c;
}

#endif /* HEADER_H_ */

src.cc

#include "header.h"

/*
int func(int a, int b)
{
   return a + b;
}*/

src1.cc

#include "header.h"

/*int test_1()
{
   int a, b, c;
   a = 3;
   b = 7;
   c = func(a, b);
   return c;
}*/

src2.cc

#include "header.h"


/*int test_2()
{
   int a, b, c;
   a = 7;
   b = 8;
   c = func(a, b);
   return c;
}*/

main.cc

int main(int argc, char** argv)
{
   test_1();
   test_2();
   test_1();
   test_2();
}

विधानसभा 3:

src.s

GAS LISTING /tmp/ccfPkzMC.s             page 1


   1                    .file   "src.cc"
   2                    .ident  "GCC: (GNU) 4.1.2 20080704 (Red Hat 4.1.2-54)"
   3                    .section    .note.GNU-stack,"",@progbits

src1.s

GAS LISTING /tmp/cckRkoWG.s             page 1


   1                    .file   "src1.cc"
   2                    .ident  "GCC: (GNU) 4.1.2 20080704 (Red Hat 4.1.2-54)"
   3                    .section    .note.GNU-stack,"",@progbits

src2.s

GAS LISTING /tmp/ccfmb3gI.s             page 1


   1                    .file   "src2.cc"
   2                    .ident  "GCC: (GNU) 4.1.2 20080704 (Red Hat 4.1.2-54)"
   3                    .section    .note.GNU-stack,"",@progbits

main.s

GAS LISTING /tmp/ccGBsR8z.s             page 1


   1                    .file   "main.cc"
   2                    .text
   3                    .align 2
   4                    .p2align 4,,15
   5                .globl main
   6                    .type   main, @function
   7                main:
   8                .LFB5:
   9 0000 31C0          xorl    %eax, %eax
  10 0002 C3            ret
  11                .LFE5:
  12                    .size   main, .-main
  13                .globl __gxx_personality_v0
  14                    .section    .eh_frame,"a",@progbits
  15                .Lframe1:
  16 0000 1C000000      .long   .LECIE1-.LSCIE1
  17                .LSCIE1:
  18 0004 00000000      .long   0x0
  19 0008 01            .byte   0x1
  20 0009 7A505200      .string "zPR"
  21 000d 01            .uleb128 0x1
  22 000e 78            .sleb128 -8
  23 000f 10            .byte   0x10
  24 0010 06            .uleb128 0x6
  25 0011 03            .byte   0x3
  26 0012 00000000      .long   __gxx_personality_v0
  27 0016 03            .byte   0x3
  28 0017 0C            .byte   0xc
  29 0018 07            .uleb128 0x7
  30 0019 08            .uleb128 0x8
  31 001a 90            .byte   0x90
  32 001b 01            .uleb128 0x1
  33 001c 00000000      .align 8
  34                .LECIE1:
  35                .LSFDE1:
  36 0020 14000000      .long   .LEFDE1-.LASFDE1
  37                .LASFDE1:
  38 0024 24000000      .long   .LASFDE1-.Lframe1
  39 0028 00000000      .long   .LFB5
  40 002c 03000000      .long   .LFE5-.LFB5
  41 0030 00            .uleb128 0x0
  42 0031 00000000      .align 8
  42      000000
  43                .LEFDE1:
  44                    .ident  "GCC: (GNU) 4.1.2 20080704 (Red Hat 4.1.2-54)"
  45                    .section    .note.GNU-stack,"",@progbits

उदाहरण 1 और उदाहरण 3 वे हैं जिन्हें मैं विशेष रूप से दिलचस्पी लेता हूं, क्योंकि उन्हें किसी तरह से उजागर करना चाहिए कि इनलाइन फ़ंक्शन और नॉट इनलाइन फ़ंक्शन के बीच अंतर क्या है (ऊपर पोस्ट के लिंक 1,2 और 3 के बाद), मैं इनलाइन संस्करण की तुलना में इनलाइन कार्यों में गुणों की कोई कमी नहीं देखता हूं। क्या कोई मेरे लिए अंतर को उजागर कर सकता है (फिर से अंक 1,2 और 3 के संदर्भ में)?


Answers

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

किसी फ़ंक्शन को सम्मिलित करना फ़ंक्शन कॉल (मंगलाचरण) के स्थान पर फ़ंक्शन की सामग्री को चिपकाने के बराबर है।

इसलिए निम्नलिखित दिए गए हैं:

void Hello()
{
  std::cout << "Hello\n";
}

int main()
{
  Hello();
  return 0;
}

जब Hello फ़ंक्शन इनबिल्ड होता है, तो आपको इसके बराबर मिलेगा:

int main()
{
  // Hello();
  std::cout << "Hello\n"; // This is the content of function Hello().
  return 0;
}

संकलक को इनलाइन फ़ंक्शंस की अनुमति है जो इनलेट के रूप में चिह्नित नहीं हैं। इस सुविधा को अक्सर अनुकूलन सेटिंग द्वारा ट्रिगर किया जाता है।

संपादन 1: इनलाइनिंग का सामान्य कारण
किसी फ़ंक्शन को इनलाइन करने का एक सामान्य कारण यह है कि जब फ़ंक्शन को कॉल करने के लिए सामग्री ओवरहेड की तुलना में छोटी या बराबर होती है।

एक फ़ंक्शन को कॉल फ़ंक्शन से संबंधित है, जैसे कि स्टैक या रजिस्टरों के लिए चलती पैरामीटर। फ़ंक्शन के आकार की परवाह किए बिना प्रोटोकॉल मौजूद है। तो, इनलाइनिंग कॉलिंग प्रोटोकॉल को हटा देगा (इस प्रकार प्रोग्राम कोड का आकार कम कर सकता है और प्रदर्शन बढ़ाएगा)।

इनलाइन का एक अन्य कारण फ़ंक्शन कॉल की मात्रा को कम करना है। कुछ प्रोसेसर में, एक शाखा अनुदेश (फ़ंक्शन कॉल), अनुदेश कैश (या पाइपलाइन) को फिर से लोड करने का कारण बनता है। इसमें समय लगता है। इनलाइनिंग फ़ंक्शन कॉल को कम करता है और निष्पादन समय में सुधार करता है।

2 संपादित करें: कोड ब्लोट
फ़ंक्शन बनाने का एक कारण कोड आकार को कम करना है। बड़े कार्यों को शामिल करने के परिणामस्वरूप कोड ब्लोट या प्रोग्राम के आकार में वृद्धि हो सकती है।

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


शायद कुछ उदाहरणों से मदद मिलेगी।

1. पारंपरिक संकलित पुस्तकालय

foo.h:

extern int x;
int * f();

foo.cpp:

#include "foo.h"

int x = 25;

int * f() { return &x; }

उपयोगकर्ता foo.h शामिल foo.h और अनुवाद इकाई में foo.cpp वाले लिंक को कॉल करने के लिए लिंक करने की आवश्यकता है। इस तरह का हर कॉल एक ही पता देता है।

2. अलग, टीयू-स्थानीय चर

foo.h:

static int x = 35;
static int * f() { return &x; }

प्रत्येक TU जिसमें foo.h शामिल है, को एक अलग और विशिष्ट फ़ंक्शन f , जिसमें कॉल करने से प्रति TU में एक अद्वितीय मूल्य प्राप्त होता है।

3. बेबी का पहला ओडीआर उल्लंघन

foo.h:

static int x = 45;
inline int * f() { return &x; }

यह हेडर-ओनली लाइब्रेरी प्रतीत होता है, लेकिन अगर foo.h को एक से अधिक TU में शामिल किया जाता है, तो यह एक ODR उल्लंघन का गठन करता है, क्योंकि f को एक से अधिक बार परिभाषित किया जाएगा, लेकिन इसकी सभी परिभाषाएं समान नहीं होंगी।

यह एक सामान्य गलती है। Workarounds में x को टेम्प्लेट बनाने या x को किसी फ़ंक्शन के साथ int & x() { static int impl = 45; return impl; } int & x() { static int impl = 45; return impl; } int & x() { static int impl = 45; return impl; } । ध्यान दें कि यदि आप static छोड़ देते हैं, तो आपको x की कई परिभाषाओं के कारण एक लिंकर त्रुटि की संभावना होगी; static प्रतीत होता है "कोड संकलन करता है"।

4. बचाव के लिए सी ++ 17: उचित हेडर-ओनली लाइब्रेरी

foo.h:

inline int x = 55;
inline int * f() { return &x; }

यह संस्करण कार्यात्मक रूप से (1) के बराबर है, लेकिन x और f की परिभाषाओं को शामिल करने के लिए एक समर्पित अनुवाद इकाई की आवश्यकता नहीं है।


बिंदु 1) का अर्थ है कि जब तक वे अलग-अलग अनुवाद इकाइयों में होते हैं, तब तक मैं अलग-अलग कार्यान्वयन दे सकता हूं

नहीं, यह कहता है कि आपके पास एक से अधिक कार्यान्वयन हो सकते हैं। यह नहीं कहता कि वे अलग हो सकते हैं। कार्यान्वयन सभी समान होना चाहिए।

मैं इस मामले में हैरान हूं कि मेरे पास एक स्रोत फ़ाइल source.cc है जो func लिए एक घोषणा के साथ है और एक शीर्षक फ़ाइल के साथ एक शीर्षक फ़ाइल है जो अनुवाद इकाई के लिए है एक जोड़ी source.cc+header.h हैडर है। और ऐसे मामले में दो घोषित किए जाते हैं कई बार func कोई मतलब नहीं होता, क्या यह सही है?

आप चाहे जितनी बार चाहे इनलाइन हो या न हो, आप जितनी चाहे उतनी ट्रांसलेशन यूनिट में एक फंक्शन का ऐलान कर सकते हैं। इनलाइन यहां कोई कारक नहीं है।

2) एक इनलाइन फ़ंक्शन या वेरिएबल की परिभाषा (C ++ 17 के बाद) अनुवाद इकाई में मौजूद होनी चाहिए जहां यह एक्सेस की जाती है।

यह सामान्य मामला है जहां मैं घोषणा से अलग करता हूं, हेडर फ़ाइल में पहला, दूसरा स्रोत फ़ाइल में है, अगर मुझे फ़ंक्शन का उपयोग करने की आवश्यकता है, तो मुझे केवल हेडर शामिल करना होगा? लिंकिंग चरण के दौरान स्रोत द्वारा पहुंच बिंदु प्रदान किया जाएगा, सही?

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

मामला 3) बताता है कि जब तक फ़ंक्शन को स्थिर घोषित नहीं किया जाता है तब तक कीवर्ड इनलाइन अनिवार्य है।

नहीं, यह नहीं कहता है कि मुझे नहीं पता कि आप इसे कैसे समझा सकते हैं। यह सिर्फ यह कहता है कि एक inline static फंक्शन में इंटरनल लिंकेज होता है, और एक inline नॉन- static फंक्शन में एक्सटर्नल लिंकेज होता है, और सब-पॉइंट्स 3.1 और 3.2 में एक्सटर्नल लिंकेज के साथ inline फंक्शन लागू होते हैं।

व्यवहार में एक फ़ंक्शन इनलाइन होना चाहिए, जब ऐसा फ़ंक्शन बहुत छोटा होता है, लेकिन हमेशा कंपाइलर इनलाइन के रूप में घोषित फ़ंक्शन को इनलाइन नहीं करता है, उदाहरण के लिए यदि इसमें लूप्स अंदर या पुनरावर्ती है (प्रभावी C ++ स्टेट्स तो)। सामान्य तौर पर यह संकलक पर निर्भर है, मुझे आश्चर्य है कि अब ...

मान लें कि मेरे पास दो कार्य हैं पहला पहला स्व-निहित है (यह आंतरिक रूप से किसी अन्य फ़ंक्शन को कॉल नहीं करता है), दूसरा एक कॉल पहले वाला है (आप मान सकते हैं कि वे तर्क के लिए दोनों 10 लाइनें हैं)। क्या इन दोनों को इनलाइन घोषित किया जाना चाहिए? क्या उन्हें हेडर फ़ाइल में घोषित किया जाना चाहिए? या क्या मुझे हेडर फ़ाइल और स्रोत फ़ाइल में कार्यान्वयन की परिभाषा अलग-अलग करनी चाहिए? क्या बेहतर होगा?

ऑप्टिमाइज़र एक फ़ंक्शन बॉडी के इनलाइन प्रतिस्थापन का प्रदर्शन करेगा या नहीं, यह inline फ़ंक्शन के साथ दृढ़ता से सहसंबद्ध नहीं है। ऑप्टिमाइज़र किसी फ़ंक्शन के इनलाइन प्रतिस्थापन का प्रदर्शन करने के लिए स्वयं पता लगाएगा कि यह inline फ़ंक्शन है या नहीं। यदि आप अपनी परिभाषा को हेडर में रखना चाहते हैं, तो आप फ़ंक्शन inline घोषित करते हैं।


ओह आदमी, मेरे पालतू peeves में से एक।

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

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

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

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

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

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

आपके सवालों के विशिष्ट जवाब:

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

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

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

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

  • कंपाइलर कब नहीं जानता कि फ़ंक्शन / विधि 'इनलाइन' कब करें?

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

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

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

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





c++ function inline