在C++中使用内联函数的优点/缺点是什么?我看到它只会提高编译器输出的代码的性能,但是使用今天的优化编译器,快速CPU,大容量存储器等(不像1980年那样<内存稀缺,一切都必须适合100KB内存)什么他们今天真的有优势吗?
通过在需要的地方内联代码,您的程序将花费更少的时间在函数调用和返回部分.它应该使你的代码变得更快,即使它变得更大(见下文).内联琐碎的访问器可以是有效内联的一个例子.
通过将其标记为内联,您可以将函数定义放在头文件中(即它可以包含在多个编译单元中,而不会让链接器抱怨)
它可以使您的代码更大(即,如果您使用内联的非平凡函数).因此,它可能会引发分页并破坏编译器的优化.
它稍微打破了你的封装,因为它暴露了你的对象处理的内部(但是,每个"私有"成员也会).这意味着您不能在PImpl模式中使用内联.
它稍微打破了你的封装2:在编译时解决了C++内联.这意味着如果您更改内联函数的代码,则需要使用它重新编译所有代码以确保它将被更新(出于同样的原因,我避免使用函数参数的默认值)
当在头文件中使用时,它会使你的头文件变大,因此会稀释有趣的信息(比如类方法列表)和用户不关心的代码(这就是我在内部声明内联函数的原因) class,但会在类主体之后的头文件中定义它,而不会在类主体内部定义它.
编译器可能会也可能不会内联您标记为内联的函数; 它也可能决定内联在编译或链接时没有标记为内联的函数.
内联工作类似于编译器控制的复制/粘贴,这与预处理器宏完全不同:宏将被强制内联,将污染所有命名空间和代码,不易调试,甚至可以完成如果编译器将它判定为效率低下.
在类本身内部定义的类的每个方法都被视为"内联"(即使编译器仍然可以决定不内联它
虚拟方法不应该是无法解决的.尽管如此,有时候,当编译器可以确切地知道对象的类型(即对象是在同一个函数体内声明和构造)时,甚至虚拟函数也会被内联,因为编译器确切地知道了对象的类型.
模板方法/函数并不总是内联的(它们在标题中的存在不会使它们自动内联).
"内联"之后的下一步是模板元编程.即通过在编译时"内联"您的代码,有时,编译器可以推断出函数的最终结果......因此,复杂的算法有时可以简化为一种return 42 ;
语句.这对我来说是极端的内联.它在现实生活中很少发生,它使编译时间更长,不会使代码膨胀,并且会使代码更快.但是像圣杯一样,不要试图在任何地方应用它,因为大多数处理都无法通过这种方式解决......不过,这仍然很酷...
:-p
内联函数更快,因为您不需要在堆栈上推送和弹出内容,如参数和返回地址; 但是,它确实使你的二进制文件略大.
它有显着差异吗?在大多数现代硬件上并不明显.但它可以产生影响,这对一些人来说已经足够了.
标记内联内容并不能保证它是内联的.这只是对编译器的建议.有时它不可能,例如当你有虚函数或有涉及递归时.有时编译器只选择不使用它.
我可以看到这样的情况产生了可检测的差异:
inline int aplusb_pow2(int a, int b) { return (a + b)*(a + b) ; } for(int a = 0; a < 900000; ++a) for(int b = 0; b < 900000; ++b) aplusb_pow2(a, b);
在古老的C和C++中,inline
就像register
:对编译器关于可能的优化的建议(仅仅是建议).
在现代C++中,inline
告诉链接器,如果在不同的转换单元中找到多个定义(不是声明),它们都是相同的,并且链接器可以自由地保留一个并丢弃所有其他转换单元.
inline
如果在头文件中定义了一个函数(无论多么复杂或"线性"),则允许多个源包含它而不会被链接器收到"多重定义"错误.
在类中定义的成员函数默认为"内联",模板函数也是如此(与全局函数相反).
//fileA.h inline void afunc() { std::cout << "this is afunc" << std::endl; } //file1.cpp #include "fileA.h" void acall() { afunc(); } //main.cpp #include "fileA.h" void acall(); int main() { afunc(); acall(); } //output this is afunc this is afunc
请注意将fileA.h包含在两个.cpp文件中,从而产生两个.cpp文件afunc()
.链接器将丢弃其中一个.如果未inline
指定,则链接器将抱怨.
内联是对编译器的建议,可以自由忽略.它适用于少量代码.
如果你的函数是内联的,它基本上插入到函数调用的代码中,而不是实际调用一个单独的函数.这可以帮助您提高速度,因为您无需进行实际通话.
它还协助CPU进行流水线操作,因为它们不必使用调用引起的新指令重新加载管道.
唯一的缺点是可能增加二进制大小,但只要功能很小,这就不会太重要了.
我现在倾向于将这些决定留给编译器(好吧,无论如何都是聪明的).编写它们的人往往对底层架构有更详细的了解.
内联函数是编译器使用的优化技术.可以简单地将内联关键字添加到函数原型中以使函数内联.内联函数指示编译器在代码中使用该函数的任何地方插入函数的完整主体.
好处 :-
它不需要函数调用开销.
它还可以在函数调用时节省堆栈上变量push/pop的开销.
它还节省了函数返回调用的开销.
它通过利用指令缓存增加了引用的局部性.
内嵌编译器也可以应用程序内优化(如果指定).这是最重要的一个,这样编译器现在可以专注于死代码消除,可以给分支预测,感应变量消除等带来更多压力.
要查看有关它的更多信息,可以点击此链接 http://tajendrasengar.blogspot.com/2010/03/what-is-inline-function-in-cc.html
我想补充一点,在构建共享库时,内联函数至关重要.如果没有内联标记函数,它将以二进制形式导出到库中.如果导出,它也将出现在符号表中.另一方面,内联函数既不会导出到库二进制文件也不会导出到符号表.
当要在运行时加载库时,这可能是至关重要的.它也可能会遇到二进制兼容感知库.在这种情况下不要使用内联.