内联函数 – 与inline关键字完全相同的是什么?

在这个链接中 ,解释了什么是内联函数,什么是内联关键字。 我正在阅读,因为我意识到我从来没有理解这两个概念的含义,以及如何在实践中使用它们。 我从我提供的链接引用和评论

内联函数或内联variables(自C ++ 17以来)是具有以下属性的函数或variables(自C ++ 17以来):

1)只要每个定义出现在不同的翻译单元中,程序中可能有多个内联函数或variables(自C ++ 17以来)的定义。 例如,可以在包含在多个源文件中的头文件中定义内联函数或内联variables(因为C ++ 17)。

这里我已经理解了问题,声明就是新标识符的说明

void func(void); 

而定义是包括实体在内的实际实现

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

1)意味着我可以给不同的实现,只要他们在不同的翻译单位(即每个源文件每头e一个实现),但我很困惑的情况下,我有一个源文件source.cc与一个func声明和一个头文件与另一个func声明的翻译单元是source.cc+header.h ,在这种情况下声明了两次func没有任何意义,对吗?

2)内联函数或variables(自C ++ 17以来)的定义必须存在于被访问的翻译单元中(不一定在访问点之前)。

这是通常的情况下,我把声明和头文件中的第一个分开,第二个是在源文件中,如果我需要使用函数,我只需要包含头部权限? 访问点将在链接阶段由源提供,是正确的?

3)具有外部链接(例如未声明为静态)的内联函数或variables(自C ++ 17以来)具有以下附加属性:1)必须在每个翻译单元中内联声明。 2)每个翻译单元都有相同的地址。

你能提供一个简单的例子吗? 我无法想象这种情况的实际情况。 情况3)指出,除非要声明的函数是静态的,否则关键字inline是强制性的。

我所说的一切到目前为止是正确的?

实际上,一个函数应该是内联的,当这样一个函数非常小的时候,但并不总是编译器会内联声明为内联的函数,例如,如果它有循环内部或recursion(Effective C ++ states)。 一般来说,这是编译器依赖,我现在奇迹…

假设我有两个函数,第一个函数是自包含的(它不会在内部调用任何其他函数),第二个函数是第一个函数(为了参数,您可以假设它们都是10行)。 他们是否应该在线声明? 他们应该在头文件中声明? 或者我应该分开头文件中的定义和源文件中的实现? 什么会更好?

编辑1

下面的答案之一是更好的,如果我通过例子工作,与相关的汇编代码分析。

我删除了以前的代码,因为它没有意义( -O3标志优化没有设置)。

我再次启动…我有5个文件header.hsrc.ccsrc1.ccsrc2.ccsrc2.cc 对于每个翻译单元,都会发布相关的汇编代码。

我以三种不同的方式处理这些文件,后来观察生成的汇编代码,这帮助我了解了inline关键字是如何工作的。

例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 

电源

 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 

电源

 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 

电源

 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点),与内联版本相比,在内联函数中我没有看到缺less任何属性。 有人可以突出我的差异(再次点1,2和3)?

也许几个例子会有所帮助。

1.传统的编译库

foo.h中:

 extern int x; int * f(); 

Foo.cpp中:

 #include "foo.h" int x = 25; int * f() { return &x; } 

用户包括foo.h并且需要在包含foo.cpp的翻译单元中链接以调用f 。 每个这样的呼叫都返回相同的地址。

2.分离,TU本地variables

foo.h中:

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

每个包含foo.h TU都会得到一个独立的函数f ,调用这个函数将导致每个TU具有唯一的值。

3.婴儿首次违反ODR

foo.h中:

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

这似乎是一个仅包含头文件的库,但是如果foo.h包含在多个TU中,则这构成ODR违例,因为f将被定义多次,但并不是所有的定义都是相同的。

这是一个常见的错误。 解决方法包括使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. C ++ 17拯救:正确的只有标题的库

foo.h中:

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

这个版本在function上等同于(1),但是不需要专门的翻译单元来包含xf的定义。

只要他们在不同的翻译单位,我可以给予不同的实施

不,它说你可以有多个实现。 它并不是说它们可以不同。 实现必须完全相同。

我感到困惑的情况下,我有一个源文件source.ccfunc声明和一个头文件与另一个声明func的翻译单位是source.cc+header.h对,并在这种情况下宣布两次func没有任何意义,是吗?

无论是否内联,您都可以根据需要随意多次声明函数。 内联在这里不是一个因素。

2)内联函数或variables(自C ++ 17以来)的定义必须存在于访问它的翻译单元中。

这是通常的情况下,我把声明和头文件中的第一个分开,第二个是在源文件中,如果我需要使用函数,我只需要包含头部权限? 访问点将在链接阶段由源提供,是正确的?

不,在链接阶段之前,内联函数的定义必须存在于每个使用它的TU中。 内联函数的目的允许在多个TU中定义; 当你想把一个函数的定义放在一个头文件中时,你使用inline

情况3)指出,除非要声明的函数是静态的,否则关键字inline是强制性的。

不,它根本就不说,我不知道你怎么能这样解释。 它只是说inline static函数具有内部链接,而inlinestatic函数具有外部链接,而3.1和3.2则适用于具有外部链接的inline函数。

实际上,一个函数应该是内联的,当这样一个函数非常小的时候,但是并不总是编译器会内联声明为内联的函数,例如,如果它有循环内部或者recursion(有效的C ++状态)。 一般来说,这是编译器依赖,我现在奇迹…

假设我有两个函数,第一个函数是自包含的(它不会在内部调用任何其他函数),第二个函数是第一个函数(为了参数,您可以假设它们都是10行)。 他们是否应该在线声明? 他们应该在头文件中声明? 或者我应该分开头文件中的定义和源文件中的实现? 什么会更好?

优化程序是否将执行函数体的内联replace与内联函数无关。 优化器将自行判断是否执行函数的内联replace,而不pipe它是否是inline函数。 如果要将其定义放在标题中,则可以内inline函数声明。

让我们来讨论inline是否被强制的问题,暂且不谈(关于这个问题有很多的讨论)。

内联函数相当于在函数调用(invocation)的位置粘贴函数的内容。

所以给以下几点:

 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; } 

允许编译器内联没有标记为内联的函数。 此function通常由优化设置触发。

编辑1:内联的常见原因
embedded函数的一个常见原因是内容小于或等于调用函数的开销。

有一个与调用函数相关的协议,比如将参数移动到堆栈或寄存器。 该协议存在与函数的大小无关。 因此,内联将删除调用协议(从而减less程序代码的大小,提高性能)。

内联的另一个原因是减less函数调用的数量。 在一些处理器中,分支指令(函数调用)使得指令高速缓冲存储器(或pipe线)被重新加载。 这需要时间。 内联减less了函数调用并提高了执行时间。

编辑2:代码膨胀
创build函数的一个原因是减less代码的大小。 内联大函数可能导致代码膨胀或程序大小的增加。

代码膨胀和函数内联处于时间与空间的折衷之下。 内联大型职能可能会加速执行,但是您正在为此交易空间。 将通用代码放入函数可能会减less程序的大小,但需要更多的时间来执行。