当前位置:  开发笔记 > 编程语言 > 正文

C++中内联函数的好处?

如何解决《C++中内联函数的好处?》经验,为你挑选了6个好方法。

在C++中使用内联函数的优点/缺点是什么?我看到它只会提高编译器输出的代码的性能,但是使用今天的优化编译器,快速CPU,大容量存储器等(不像1980年那样<内存稀缺,一切都必须适合100KB内存)什么他们今天真的有优势吗?



1> paercebal..:

好处

通过在需要的地方内联代码,您的程序将花费更少的时间在函数调用和返回部分.它应该使你的代码变得更快,即使它变得更大(见下文).内联琐碎的访问器可以是有效内联的一个例子.

通过将其标记为内联,您可以将函数定义放在头文件中(即它可以包含在多个编译单元中,而不会让链接器抱怨)

缺点

它可以使您的代码更大(即,如果您使用内联的非平凡函数).因此,它可能会引发分页并破坏编译器的优化.

它稍微打破了你的封装,因为它暴露了你的对象处理的内部(但是,每个"私有"成员也会).这意味着您不能在PImpl模式中使用内联.

它稍微打破了你的封装2:在编译时解决了C++内联.这意味着如果您更改内联函数的代码,则需要使用它重新编译所有代码以确保它将被更新(出于同样的原因,我避免使用函数参数的默认值)

当在头文件中使用时,它会使你的头文件变大,因此会稀释有趣的信息(比如类方法列表)和用户不关心的代码(这就是我在内部声明内联函数的原因) class,但会在类主体之后的头文件中定义它,而不会在类主体内部定义它.

内联魔术

编译器可能会也可能不会内联您标记为内联的函数; 它也可能决定内联在编译或链接时没有标记为内联的函数.

内联工作类似于编译器控制的复制/粘贴,这与预处理器宏完全不同:宏将被强制内联,将污染所有命名空间和代码,不易调试,甚至可以完成如果编译器将它判定为效率低下.

在类本身内部定义的类的每个方法都被视为"内联"(即使编译器仍然可以决定不内联它

虚拟方法不应该是无法解决的.尽管如此,有时候,当编译器可以确切地知道对象的类型(即对象是在同一个函数体内声明和构造)时,甚至虚拟函数也会被内联,因为编译器确切地知道了对象的类型.

模板方法/函数并不总是内联的(它们在标题中的存在不会使它们自动内联).

"内联"之后的下一步是模板元编程.即通过在编译时"内联"您的代码,有时,编译器可以推断出函数的最终结果......因此,复杂的算法有时可以简化为一种return 42 ;语句.这对我来说是极端的内联.它在现实生活中很少发生,它使编译时间更长,不会使代码膨胀,并且会使代码更快.但是像圣杯一样,不要试图在任何地方应用它,因为大多数处理都无法通过这种方式解决......不过,这仍然很酷...
:-p


.它在现实生活中很少发生,它使编译时间更长,不会使代码膨胀,并且会使代码更快.但是像圣杯一样,不要试图在任何地方应用它,因为大多数处理都无法通过这种方式解决......不过,这仍然很酷...
@PravasiMeet:这是C++.假设您将DLL /共享库提供给客户端,客户端编译它.内联函数foo,使用成员变量X并执行工作Y将在客户端的代码中内联.假设您需要提供DLL的更新版本,其中您将成员变量更改为Z,并在工作Y之外添加工作YY.客户端只是将DLL复制到他们的项目中,而BOOM,因为foo的代码在他们的二进制文件中不是您编写的更新代码...尽管客户端没有合法访问您的私人代码,但内联使其非常"公开".

2> Brian R. Bon..:

内联函数更快,因为您不需要在堆栈上推送和弹出内容,如参数和返回地址; 但是,它确实使你的二进制文件略大.

它有显着差异吗?在大多数现代硬件上并不明显.但它可以产生影响,这对一些人来说已经足够了.

标记内联内容并不能保证它是内联的.这只是对编译器的建议.有时它不可能,例如当你有虚函数或有涉及递归时.有时编译器只选择不使用它.

我可以看到这样的情况产生了可检测的差异:

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


虽然呼叫本身确实很重要,但这只是通过内联使用获得的微小收益.主要的好处是,编译器现在可以看到指针彼此不是别名的地方,调用者的变量最终会出现在被调用者中,依此类推.因此,以下优化更重要.
它可能在这个片段中没有区别,因为函数的结果从未使用过,函数也没有副作用.我们看到图像处理中的内联可以获得可测量的性能提升.
因为我怀疑内联对上述情况没有任何影响.用gcc 4.01编译.版本1强制使用内联:48.318u 1.042s 5:51.39 99.4%0 + 0k 0 + 0io 0pf + 0w版本2强制无内联348.311u 1.019s 5:52.31 99.1%0 + 0k 0 + 0io 0pf + 0w这是一个很好的例子是常识是错误的.
没有区别的原因可能是编译器可能会自行内联; 或者代码很小,因此没有代码预取问题.
@einpoklum由于这个原因,编译器甚至可能已经优化了整个循环.

3> Emilio Garav..:

在古老的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指定,则链接器将抱怨.



4> paxdiablo..:

内联是对编译器的建议,可以自由忽略.它适用于少量代码.

如果你的函数是内联的,它基本上插入到函数调用的代码中,而不是实际调用一个单独的函数.这可以帮助您提高速度,因为您无需进行实际通话.

它还协助CPU进行流水线操作,因为它们不必使用调用引起的新指令重新加载管道.

唯一的缺点是可能增加二进制大小,但只要功能很小,这就不会太重要了.

我现在倾向于将这些决定留给编译器(好吧,无论如何都是聪明的).编写它们的人往往对底层架构有更详细的了解.



5> 小智..:

内联函数是编译器使用的优化技术.可以简单地将内联关键字添加到函数原型中以使函数内联.内联函数指示编译器在代码中使用该函数的任何地方插入函数的完整主体.

好处 :-

    它不需要函数调用开销.

    它还可以在函数调用时节省堆栈上变量push/pop的开销.

    它还节省了函数返回调用的开销.

    它通过利用指令缓存增加了引用的局部性.

    内嵌编译器也可以应用程序内优化(如果指定).这是最重要的一个,这样编译器现在可以专注于死代码消除,可以给分支预测,感应变量消除等带来更多压力.

要查看有关它的更多信息,可以点击此链接 http://tajendrasengar.blogspot.com/2010/03/what-is-inline-function-in-cc.html


1)这是一个建议,而不是一条指令2)如果一个常用的函数内联很多,它可能会导致更多的缓存未命中,因为代码大小会增加
链接最后是您的个人博客吗?如果是,你应该声明它,否则它看起来像垃圾邮件.

6> doc..:

我想补充一点,在构建共享库时,内联函数至关重要.如果没有内联标记函数,它将以二进制形式导出到库中.如果导出,它也将出现在符号表中.另一方面,内联函数既不会导出到库二进制文件也不会导出到符号表.

当要在运行时加载库时,这可能是至关重要的.它也可能会遇到二进制兼容感知库.在这种情况下不要使用内联.

推荐阅读
无名有名我无名_593
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有