据我所知,内联函数是一种优化以提高性能,因此它的运行速度应该与宏一样快。内联函数的代码应尽可能短。
我想知道在内联函数中嵌入函数调用是否有意义。如果答案是肯定的,在什么情况下,有哪些限制?
实际上,我之所以问这个问题,是因为我查看了某人的代码,该代码正在从内联函数调用诸如"socket()","sendto()"和"memset()"之类的函数;在我看来,它覆盖了内联函数的目的。
注意:在我的代码中,没有使用对函数的任何条件调用,内联函数只是将参数传递给被调用的函数。
我想知道在内联函数中嵌入函数调用是否有意义。
当然有。内联对函数的调用仍然是一种优化,消除了该函数调用的成本,并允许在调用函数的上下文中进行进一步优化,无论它是否反过来调用其他函数。
在什么情况下,有哪些限制?
我不知道你所说的"上下文"是什么意思;但是在内联函数中可以做什么没有任何限制。声明函数inline
的唯一语义效果是允许多个相同的定义,并且要求在使用该函数的任何翻译单元中进行定义。在所有其他方面,它与任何其他函数定义相同。
根据要求发布评论作为答案:
如果编写代码的人认为inline
对性能有任何有意义的影响,那么他显然没有"做正确的事"。
性能来自正确的算法选择和避免缓存未命中。
头痛来自1991年可能有效的幼稚过早优化技术
我认为内联代码不能包含函数调用的先验原因。
撇开参数传递不谈,内联会按原样插入代码行,从而减少调用开销并允许本地/临时优化。
例如,当使用 MyInline(false)
调用时,inline void MyInline(bool Perform) { if (Perform) memset(); }
很可能被跳过。
还可以允许内联内部函数调用,从而带来更多(微)优化机会。
编译器将选择何时内联。而且,您应该避免以暴露您的实现为代价来尝试过早的优化。
编译器可能能够优化您正在调用的函数的转发。即使您不使用内联关键字,它也可能会使用优化标志来做到这一点。
使用inline
关键字的时间是当您想要制作一个仅在多个项目中使用的头文件而不必使用链接库时。实际上,这根本不意味着"内联",它意味着"只有一个定义",即使跨调用函数的编译单元也是如此。
无论如何,您应该查看此维基问题/答案:
内联函数在C++中的优势?
这是完全有道理的。
考虑一个由两个可能的执行分支组成的函数 — 当某些条件成立时(大多数时间)激活的快速路径和慢速路径。
内联整个事情会导致代码的大小增加,而几乎没有好处。缓慢的路径复杂性可能会阻止编译器内联函数。
如果您将慢速路径设置为单独的功能,则会打开一个有趣的机会。
它可以内联条件和快速路径,而慢速路径仍然是函数调用。内联快速路径允许在大多数情况下避免函数调用开销。慢速路径已经很慢,因此呼叫开销可以忽略不计。
首先,在C++中,"内联"函数(在头文件中声明或标记为这样)只是对编译器的建议。编译器本身将决定是否实际使其内联。
内联函数有三个原因:
- 将另一轮变量推送到堆栈上是昂贵的,分支到程序中的新点也是如此。
- 有时我们可以对函数的中间体进行局部优化(尽管我不会指望它!
- 将函数的定义放在头文件中(解决方法)。
以以下示例为例
void NonInlinable(int x);
inline void Inline() { NonInlinable(10);}
这很有意义。我删除了 1 个函数调用,所以如果 NonInlineable 非常快,那么这可能是一个巨大的加速。因此,无论我是否调用函数,我仍然可能想要内联调用。
再举一个例子:
inline int Inline(int y) {return y/10;}
//main
...
int x = 5;
int y = Inline(5);
int z = x % 10;
模运算和设计运算通常由相同的指令计算。一个非常好的编译器,可以在 1 条汇编指令中计算 y 和 z!魔法
所以在我看来,一个更好的问题是我什么时候不应该使用内联函数:
- 当我想将定义与声明分开时(可读性非常好的做法,过早的优化是万恶之源)。
- 当我想隐藏我的实现/使用良好的封装时。