C ++内联函数?


74

我为什么要做这样的事情:

inline double square (double x) { return x*x;}

代替

double square (double x) { return x*x;}

有区别吗?



1
其实有很多重复和接近重复:stackoverflow.com/search ? q=c%2B%2B+inline 。有些答案比其他答案更好,有些答案错误地指出该inline关键字导致该函数在所有调用站点上都内联,依此类推。那可能不是最接近的骗子。
史蒂夫·杰索普

另请参阅C ++常见问题解答中的内联函数。他们对内联有很好的处理。
jww

Answers:


87

前者(使用inline)使您可以将该函数放在头文件中,该文件可以包含在多个源文件中。使用inline使标识符成为文件范围,就像声明它一样static。如果不使用inline,则会从链接器中收到多个符号定义错误。

当然,这是对编译器的提示,它暗示应该将函数内联编译到使用该函数的位置(避免了函数调用的开销)。不需要编译器对inline提示进行操作。


1
我认为内联的目的是为了使编译器“扩展”所调用函数的内容,因此不会进行vtable查找(或指令跳转到CPU级别的函数)。
DJ。

您的第一点是预期目的的[有用]副作用吗?
伊恩·弗莱顿

@Ian Fleeton:确实是副作用。如果内联标识符没有文件范围,则根本不可能将内联函数定义放在头文件中。
2011年

10
@Greg:它的行为并不像以前那样static。如果这样做的话,每个翻译单元将对其函数副本拥有自己的所有权,并且链接程序会将它们全部视为不同的函数(碰巧具有相同的名称)。相反,inline指示链接器,如果看到此功能的不同定义,则它们都是相同的,必须合并为一个。但是,忽略该细节,它在大多数情况下的行为就像是static
GManNickG

1
@DJ:inline无法阻止vtable查找,您需要为此进行调用虚拟化
Ben Voigt

26

在现代编译器上,可能没有太大区别。它可以不被内联inline,它可能不会被内联inline


从我的参考和10岁的经验出发,这是有道理的。
伊恩·弗莱顿

26

是,有一点不同。https://isocpp.org/wiki/faq/inline-functions

当指定函数为内联函数时,将导致编译器将方法的代码放在被调用的位置。

void myfunc() {
  square(2);
}

等同于

void myfunc() {
   2 * 2;
}

调用一个函数有助于代码清晰,但是当调用该函数时,必须将本地状态推送到堆栈中,为此方法设置一个新的本地状态,完成后,需要弹出先前的状态。那是很多开销。

现在,如果您提高了优化级别,则编译器将做出诸如展开循环或内联函数之类的决策。编译器仍然可以忽略内联语句。


2
我认为使用gcc您可以使用compile标志-Winline来警告何时不内联函数。-Werror如果您是按摩师,可以将其与。
patmanpato

“编译器仍然可以忽略内联语句。” 实际上,每个现代编译器都这样做。
瓦尔说莫妮卡(Monica)


2

inline过程抽象的概念配合得很好:

inline double square (double x) { return x*x;}

int squareTwice(double x) {
    double first = square(x);
    double second = square(x);
    return first * second; 
}

上面的内容基本上类似于以下内容:

int squareTwice(double x) {
    double first = x*x;
    double second = x*x;
    return first * second; 
}

发生这种情况的原因是,当编译器内联扩展函数调用时,该函数的代码将插入到调用者的代码流中。因此,从程序上将第二个示例抽象为第一个示例可能会更容易。

过程抽象使将例程分解为更易于阅读的较小子例程成为可能(尽管这可以作为样式选择)。


1

如果编译器遵从,则内联函数将在被调用的代码中包括内联函数,就好像没有调用任何函数(就像您已将逻辑放在调用函数中一样),并避免了函数调用开销。


6
即使指定了inline关键字,编译器也不需要内联该函数。
马龙

1
@Alex Marlon并不是说编译器不会内联函数,只是说它不必这样做。那是完全不同的东西。
2014年
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.