GNU C++ 编译器 ((GCC) 5.2.0) 本身就擅长 "inlining" 吗?
Is the GNU C++ compiler ((GCC) 5.2.0) good at "inlining" by itself?
我不是在问为什么或什么时候应该在某些代码中使用 inline
。
我在我认为常用的地方使用 inline
(比如在 get/set 函数中)。我在堆栈上阅读了一些不寻常的例子,其中 inline
听起来是必要的。我不确定我是否会在我的代码中识别出这种情况......我的意思是,直到我遇到问题......
所以我想知道对于通常情况,编译器是否处理得和我一样好,甚至更好...
我想避免 inline
的原因是为了避免在 header 之后实施......关于这个问题,我脑海中浮现出一个问题:
编译器(在我的问题中我总是考虑 GCC 编译器)是否能够 inline
header 中未实现的功能?
n.b。 : 我不知道 C++14 中是否有关于 inline
的一些内部变化。
编译器可以内联同一文件中使用的函数(技术上,"compilation unit"),但在编译不同文件时不能,因为它没有源代码。这就是内联函数应该放在头文件中的原因。
如果没有某种示例代码,很难确定编译器将做什么(即使有代码,也可能非常困难)。
一般来说,如果函数很小,编译器将在编译期间内联具有可用源代码的函数(以及其他如果启用 lto(link 时间优化)。如果您希望能够将函数编译成目标文件并内联函数,则必须使用 lto。
在大多数情况下,只调用一次的大型静态函数也会被内联。
当您有多个调用并且函数是 "more than tiny in size" 时,问题就来了 - 换句话说,超过 3-4 行长。然后编译器必须在内联和膨胀代码之间取得平衡,而不是内联和调用成本。这是一个很难做到正确的平衡。 Profile-driven optimization 在这里可以提供很多帮助,但一般来说,编译器大部分都会正确,但不能完全保证 - 如果有疑问(这很重要),请使用您的应用程序的基准测试,并衡量它是否变得更好具有强制内联属性。
首先,内联一些东西,即要求在调用点内联替换函数体并不意味着实现被限制这样做:
7.1.2 Function specifiers
2 A function declaration (8.3.5, 9.3, 11.3) with an inline specifier declares an inline function. The inline specifier indicates to the implementation that inline substitution of the function body at the point of call is to be preferred to the usual function call mechanism. An implementation is not required to perform this inline substitution at the point of call; however, even if this inline substitution is omitted, the other rules for inline functions defined by 7.1.2 shall still be respected.
仅凭这一点就应该让人觉得依赖编译器优化(或者这样做很重要)关于这个主题是一种模糊的启发式方法。例如,我们知道编译器很难内联函数指针调用,但这并不重要。
有一些标准要求内联的语言结构示例,这不是成为一个好的编译器的问题,而是一个兼容的编译器的问题。
闭包类型的函数调用运算符
5.1.2
5 The closure type for a non-generic lambda-expression has a public inline function call operator (...) For a generic lambda, the closure type has a public inline function call operator member template (...)
constexpr 函数
7.1.5
2 (...) constexpr functions and constexpr constructors are implicitly
inline (7.1.2).
已删除函数
8.4.3
A deleted function is implicitly inline. [ Note: The one-definition rule (3.2) applies to deleted definitions.
— end note ] A deleted definition of a function shall be the first declaration of the function or, for an explicit
specialization of a function template, the first declaration of that specialization.
其他示例是在 class 定义中定义的成员函数和在 class 的友元声明中定义的函数。内联并非在所有情况下都是最佳选择(会增加程序大小),因此对于性能关键部分,我建议进行基准测试并自行决定;毕竟Do inline functions improve performance?
我不是在问为什么或什么时候应该在某些代码中使用 inline
。
我在我认为常用的地方使用 inline
(比如在 get/set 函数中)。我在堆栈上阅读了一些不寻常的例子,其中 inline
听起来是必要的。我不确定我是否会在我的代码中识别出这种情况......我的意思是,直到我遇到问题......
所以我想知道对于通常情况,编译器是否处理得和我一样好,甚至更好...
我想避免 inline
的原因是为了避免在 header 之后实施......关于这个问题,我脑海中浮现出一个问题:
编译器(在我的问题中我总是考虑 GCC 编译器)是否能够 inline
header 中未实现的功能?
n.b。 : 我不知道 C++14 中是否有关于 inline
的一些内部变化。
编译器可以内联同一文件中使用的函数(技术上,"compilation unit"),但在编译不同文件时不能,因为它没有源代码。这就是内联函数应该放在头文件中的原因。
如果没有某种示例代码,很难确定编译器将做什么(即使有代码,也可能非常困难)。
一般来说,如果函数很小,编译器将在编译期间内联具有可用源代码的函数(以及其他如果启用 lto(link 时间优化)。如果您希望能够将函数编译成目标文件并内联函数,则必须使用 lto。
在大多数情况下,只调用一次的大型静态函数也会被内联。
当您有多个调用并且函数是 "more than tiny in size" 时,问题就来了 - 换句话说,超过 3-4 行长。然后编译器必须在内联和膨胀代码之间取得平衡,而不是内联和调用成本。这是一个很难做到正确的平衡。 Profile-driven optimization 在这里可以提供很多帮助,但一般来说,编译器大部分都会正确,但不能完全保证 - 如果有疑问(这很重要),请使用您的应用程序的基准测试,并衡量它是否变得更好具有强制内联属性。
首先,内联一些东西,即要求在调用点内联替换函数体并不意味着实现被限制这样做:
7.1.2 Function specifiers
2 A function declaration (8.3.5, 9.3, 11.3) with an inline specifier declares an inline function. The inline specifier indicates to the implementation that inline substitution of the function body at the point of call is to be preferred to the usual function call mechanism. An implementation is not required to perform this inline substitution at the point of call; however, even if this inline substitution is omitted, the other rules for inline functions defined by 7.1.2 shall still be respected.
仅凭这一点就应该让人觉得依赖编译器优化(或者这样做很重要)关于这个主题是一种模糊的启发式方法。例如,我们知道编译器很难内联函数指针调用,但这并不重要。
有一些标准要求内联的语言结构示例,这不是成为一个好的编译器的问题,而是一个兼容的编译器的问题。
闭包类型的函数调用运算符
5.1.2
5 The closure type for a non-generic lambda-expression has a public inline function call operator (...) For a generic lambda, the closure type has a public inline function call operator member template (...)
constexpr 函数
7.1.5
2 (...) constexpr functions and constexpr constructors are implicitly inline (7.1.2).
已删除函数
8.4.3
A deleted function is implicitly inline. [ Note: The one-definition rule (3.2) applies to deleted definitions. — end note ] A deleted definition of a function shall be the first declaration of the function or, for an explicit specialization of a function template, the first declaration of that specialization.
其他示例是在 class 定义中定义的成员函数和在 class 的友元声明中定义的函数。内联并非在所有情况下都是最佳选择(会增加程序大小),因此对于性能关键部分,我建议进行基准测试并自行决定;毕竟Do inline functions improve performance?