21

根据维基百科 C++ 文章

C++ 旨在为程序员提供选择,即使这使程序员有可能做出错误的选择。

如果它是这样设计的,为什么没有标准的方法来强制编译器内联某些东西,即使我可能错了?

或者我可以问为什么inline关键字只是一个提示?

我想我在这里别无选择。

在 OOP 世界中,我们在对象上调用方法,应该避免直接访问成员。如果我们不能强制内联访问器,那么我们就无法编写高性能但仍可维护的应用程序。

(我知道许多编译器实现了自己的强制内联方式,但这很丑陋。使用宏在类上制作内联访问器也很丑陋。)

编译器总是比程序员做得更好吗?

4

5 回答 5

18

编译器如何内联递归函数(特别是如果编译器不支持尾调用优化,即使支持,该函数也不支持尾调用优化)。

这只是编译器应该决定内联是否实用的原因之一。可能还有其他我现在想不到的。

于 2011-05-24T09:38:21.863 回答
5

编译器总是比程序员做得更好吗?

不,并非总是如此……但程序员更容易出错,并且不太可能在几年内保持最佳调整。底线是,内联仅在函数非常小的情况下(对于至少一个常见/重要的代码路径)有助于提高性能,但它可以帮助大约一个数量级,当然这取决于许多事情。程序员评估通常是不切实际的,更不用说仔细观察函数的重要性了,阈值可能会因编译器实现选择、命令行选项、CPU 模型等而有所不同。有很多事情可能会突然膨胀函数 - 任何非内置类型都可以触发各种不同的行为(尤其是在模板中),使用运算符(甚至new) 可以重载,调用约定和异常处理步骤的冗长对程序员来说通常并不明显。

很有可能的是,如果编译器没有内联一些小到足以让您期待有用的性能改进的东西,那么编译器就会意识到一些实现问题,而您并没有这样做实际上会使情况变得更糟。在那些编译器可能会采用任何一种方式并且您刚刚超过某个阈值的灰色情况下,无论如何性能差异都不太可能显着。

此外,一些程序员(包括我自己)可能很懒惰,故意滥用inline作为将实现放在头文件中的一种方便方法,绕过 ODR,即使他们知道这些函数很大并且如果编译器(被需要)实际内联它们。这并不排除强制内联关键字/符号……它只是解释了为什么很难改变围绕当前inline关键字的期望。

于 2011-05-24T10:05:33.450 回答
3

或者我可以问为什么 inline 关键字只是一个提示?

因为你“可能”比编译器更了解。

大多数时候,对于未标记为内联(并且正确声明/定义)的函数,编译器将根据其配置和实现自行评估该函数是否可以内联。

例如,如果代码不长和/或太复杂,大多数编译器将自动内联在头文件中完全定义的成员函数。那是因为函数在标题中可用,为什么不尽可能多地内联它呢?但是这不会发生,例如在 Visual Studio 的调试模式下:在调试中,调试信息仍然需要映射函数的二进制代码,因此它避免内联,但仍会内联标记为内联的函数,因为用户需要它。如果你想标记函数你不需要有调试时信息(如简单的 getter)同时在调试时获得更好的性能,这很有用。在发布模式下(默认情况下),编译器将积极内联它所能做的一切,

因此,一般的想法是,如果您以有助于编译器内联的方式进行编码,它将尽可能多地内联。如果您以难以或不可能内联的方式编写代码,它将避免。如果您将某些内容标记为内联,您只需告诉编译器,如果它发现很难内联但并非不可能内联,则应将其内联。

由于内联取决于调用者和被调用者的上下文,因此没有“规则”。通常建议的是简单地忽略显式内联标记函数,但在两种情况下:

  1. 如果您需要将函数定义放在标题中,则只需内联即可;模板(成员或非成员)函数和其他只是快捷方式的实用函数通常是这种情况;
  2. 例如,如果您希望特定编译器在编译时以特定方式运行,例如将某些成员函数标记为内联,即使在 Visual Studio 编译器的调试配置中也是如此。

编译器总是比程序员做得更好吗?

不,这就是为什么有时使用 inline 关键字会有所帮助的原因。程序员有时可以比编译器更好地了解什么是必要的。例如,如果程序员希望它的二进制文件尽可能小,这取决于代码,内联可能是有害的。在需要速度性能的应用程序中,积极地内联会很有帮助。编译器如何知道需要什么?必须对其进行配置并允许以细粒度的方式了解真正想要内联的内容。

于 2011-05-24T09:59:49.700 回答
0

错误的假设。

办法。它是拼写的#define。对于许多早期的 C 项目来说,这已经足够了。inline有足够的不同 - 提示,更好的语义 - 它可以添加到宏之外。但是一旦你两者兼得,就没有第三个选项的余地了,一个语义更好但不是可选的。

于 2011-05-24T12:27:12.780 回答
-1

如果你真的需要强制内联函数(为什么?),你可以这样做:复制代码并粘贴,或者使用宏。

于 2011-05-24T09:53:38.980 回答