C++ 是GNU C++;编译器((GCC)5.2.0)擅长;内联“;独自一人?

C++ 是GNU C++;编译器((GCC)5.2.0)擅长;内联“;独自一人?,c++,gcc,g++,c++14,C++,Gcc,G++,C++14,我不是问为什么或者什么时候应该在某些代码中使用inline 我使用inline在我认为很常见的地方(比如在get/set函数中)。我在堆栈上读到了一些不同寻常的例子,其中内联听起来很有必要。我不确定我是否能在我的代码中识别出这样的情况。。。我是说,在我遇到问题之前 所以我想知道,在通常情况下,编译器是否能像我一样处理这些问题,甚至可能更好 我希望避免内联的原因是为了避免必须在头中实现。。。关于这一点,我突然想到一个问题: 是编译器(我总是认为我的问题中的GCC编译器)能够内联一个未在页眉?< /

我不是问为什么或者什么时候应该在某些代码中使用
inline

我使用
inline
在我认为很常见的地方(比如在get/set函数中)。我在堆栈上读到了一些不同寻常的例子,其中
内联
听起来很有必要。我不确定我是否能在我的代码中识别出这样的情况。。。我是说,在我遇到问题之前

所以我想知道,在通常情况下,编译器是否能像我一样处理这些问题,甚至可能更好

我希望避免内联的原因是为了避免必须在头中实现。。。关于这一点,我突然想到一个问题:

是编译器(我总是认为我的问题中的GCC编译器)能够<代码>内联一个未在页眉?< /p>中实现的函数?
n、 b:我不知道C++14中的
内联
是否有一些内部更改。

编译器可以内联在同一个文件中使用的函数(技术上称为“编译单元”),但在编译不同的文件时不能内联,因为它没有源代码。这就是为什么内联函数应该放在头文件中。

如果没有某种示例代码,很难确定编译器将做什么(即使有代码,也可能非常困难)

一般来说,如果函数很小,编译器将内联编译过程中源代码可用的函数(如果启用lto(链接时间优化),则其他函数也将内联。如果希望能够将函数编译到目标文件并内联函数,则必须使用lto

在大多数情况下,只调用一次的大型静态函数也将内联


当您有多个调用且函数“尺寸太小”时,问题就会出现-换句话说,长度超过3-4行。然后编译器必须在内联和膨胀代码之间进行平衡,而不是内联和调用成本之间进行平衡。这是一个很难做到的平衡。配置文件驱动的优化在这方面有很大帮助,但总的来说,编译器基本上都能做到正确,但根本不能保证——如果有疑问的话(这一点很重要),使用应用程序的基准测试,并通过强制内联属性衡量它是否变得更好。

首先内联一些东西,即需要在调用点内联替换函数体并不意味着实现必须这样做

7.1.2函数说明符

2 A功能声明(8.3.5、9.3、11.3)使用内联说明符声明内联函数。内联说明符向实现指示,在调用点对函数体进行内联替换比通常的函数调用机制更可取。实现不需要在调用点执行此内联替换。;但是,即使省略了此内联替换,仍应遵守7.1.2中定义的内联函数的其他规则。

单凭这一点就可以看出,依赖编译器优化(或者这样做很重要)是一种模糊启发。例如,我们知道编译器很难内联函数指针调用,但这并不重要

有一些标准要求内联的语言构造示例,这不是一个好的编译器,而是一个兼容的编译器

闭包类型的函数调用运算符 5.1.2

5非泛型lambda表达式的闭包类型具有公共内联函数调用运算符(…)。对于泛型lambda,闭包类型具有公共内联函数调用运算符成员模板(…)

constexpr函数 7.1.5

2(…)constexpr函数和constexpr构造函数是隐式的 内联(7.1.2)

删除的函数 8.4.3

已删除的函数是隐式内联的。[注意:一个定义规则(3.2)适用于已删除的定义。 -结束注释]删除的函数定义应为该函数的第一个声明,或 函数模板的专门化,该专门化的第一个声明


其他示例包括在类定义中定义的成员函数和在类的友元声明中定义的函数。内联不是所有情况下的最佳选择(可能会增加程序大小)因此,对于性能关键部分,我建议您自己进行基准测试和决定;毕竟,如果您在头上实现了非内联函数,那么当从多个源中包含多重定义符号时,您将得到多重定义符号的链接器错误files@NikosAthanasiou好吧,我不想在标题中实现…正如我在question@juanchopanza,“Is/Does…?”我赌Does,我输了…你说的是“内联”方法,即在类定义中实现的方法?除非使用链接时间优化(通过-flto标记进行编译和链接),否则gcc不能从另一个编译单元内联函数-但在这种情况下,它做得相当好。我没有添加代码,因为正如您所说,“即使使用代码,也可能非常困难”。而且(可能我认为这是显而易见的,所以我错了)但是,GET/SET函数不会占用更多的一行。到目前为止,我从来没有使用过<代码> LTO 标志,我会在Futur.Tx中考虑它。对于你来说,对于GETTTE/SETER函数,我将它们内嵌到类声明中。这样,编译器就可以内嵌。我也用来内联它们,但是有时候你必须处理FO。rward声明…依赖性…我尝试使我的头尽可能轻。当然,正如我所说的,如果性能非常重要,那么基准测试、配置文件和检查代码实际花费的时间。大多数函数只调用了几次,实际上没有多大关系…我不知道如何执行