C++ 内联函数:这样声明,这样定义,还是两者兼而有之?为啥?
Posted
技术标签:
【中文标题】C++ 内联函数:这样声明,这样定义,还是两者兼而有之?为啥?【英文标题】:C++ inline functions: declare as such, define as such, or both? Why?C++ 内联函数:这样声明,这样定义,还是两者兼而有之?为什么? 【发布时间】:2017-06-27 19:32:37 【问题描述】:以下代码段编译没有问题,即使 foo
被内联定义但未如此声明,bar
被声明内联但未如此定义。
int foo();
inline int foo() return 3;
inline int bar();
int bar() return 4;
inline int foobar();
inline int foobar() return 5;
int main()
// ...
我的第一个问题:编译器是否将foo
读取为内联? bar
呢?这是 C++ 标准规定的吗?
我的第二个问题:以下哪一个是声明和定义内联函数的最佳实践?是foo
吗? bar
?或foobar
?为什么?
inb4 我阅读了一些与此相关的其他帖子,但没有一个直接回答我的问题。
This 的答案似乎暗示foo
是内联的,但对bar
只字未提。它也没有解释 为什么 foo
比其他人更受欢迎。 This 回答谈到我应该何时使用内联函数。这不是我关心的问题:我已经决定使用内联函数。我的问题(确切地说是问题 2)是我是否应该这样声明、这样定义,或两者兼而有之,以及为什么其中一种约定比其他约定更好。 This 问题似乎更接近我的关注,但没有人回答。
【问题讨论】:
我认为两者都违反了单一定义规则:en.cppreference.com/w/cpp/language/definition 像 return 3;
这样简单的函数几乎肯定会被内联,无论您如何定义/声明它。
@James 这是一个简单的代码 sn-p 来演示我的问题。发布一个“现实”的功能会分散我的主要观点。
@Richard 定义了三个函数:foo、bar 和 foobar。哪两个违反了单一定义规则? (怎么回事?我只定义了一次函数。)另外请参阅我的原始问题。 (第一个问题和第二个问题)
@RichardCritten - 没有。每个函数只定义一次。它们有一个可能相互冲突的声明,但只有一个定义。
【参考方案1】:
对于成员函数是正确的,对于非成员函数没有明确定义(我相信)
参见 ISO C++ 标准中的 §10.1.6。
内联说明符只能应用于声明或 变量或函数的定义
和
带有 inline 说明符的函数声明(11.3.5、12.2.1、14.3)声明了一个内联函数。
它没有明确说明如果内联说明符只修改函数的定义会发生什么。
我们可以确定的是,这样的成员函数肯定会被标记为内联(感谢 James Curran)。
参见第 12.2.1 节。
内联成员函数(无论是静态的还是非静态的)也可以是 在其类定义之外定义提供其 类定义中的声明或其外部的定义 类定义将函数声明为 inline 或 constexpr。
GCC 和非成员情况下的所有三个函数
与 GCC -O1
C++ 模式一样,提到的每个函数都是内联的。
代码:
#include "stdio.h"
int foo();
inline int foo() int i; for(i=0;i<100000;i++); return i+3;
inline int bar();
int bar() int i; for(i=0;i<100000;i++); return i+4;
inline int foobar();
inline int foobar() int i; for(i=0;i<100000;i++); return i+5;
int foobar2();
int foobar2() int i; for(i=0;i<100000;i++); return i+6;
int main()
int a,b,c,d;
a=foo();
b=bar();
c=foobar();
d=foobar2();
printf("%d %d %d %d", a, b, c, d);
拆解:
我们只能看到foobar2
被调用了。
与-O2
和-O3
一样,inline
并不重要。编译器将自行决定(在上面的例子中,所有 4 个函数都是内联的)。
【讨论】:
好的,很高兴知道。从您的示例看来,gcc 内联了所有 3 个。 你的回答大多没用。知道特定编译器使用一组特定选项内联了什么并不有趣。答案应包含标准中的引用,解释所有这些声明/定义对之间的区别。 @EdgarRokyan 谢谢。我从标准中添加了相关信息。 没有函数是“保证内联的。”你能做的最好的就是“保证被标记为可内联”。编译器将做出最终决定。【参考方案2】:(注意:我重新打开了这个问题,因为这不是引用的旧问题的重复。那个问题涉及设计;这是关于语法的)。
现在,参考 OP 在他关于 inline in definition and declaration 的问题中引用的问题,答案指出如果声明位于头文件中,则它具有“内联”(“条形样式”),因为使用该标头的其他源文件将尝试链接到它,就好像它是非内联函数和文件一样。
就个人而言,我会使用
inline int foobar() return 5;
在头文件中没有单独的声明。 (我总觉得如果太大不能放在表头,那就太大了不能内联。)
【讨论】:
嗯,好点。我可能也会这样做。只是我看到人们将成员函数声明为非内联的地方,然后将它们(在头文件中)定义为内联,这让我想清除这段语法细节。 @HazySmoke 成员函数在默认情况下在类主体中定义时是内联的,这在 C++ 标准中是必需的。 @Keyu Gan 我的意思是它在课堂上正常声明。然后在类体之外,它被定义为内联。并且是在头文件中定义的。以上是关于C++ 内联函数:这样声明,这样定义,还是两者兼而有之?为啥?的主要内容,如果未能解决你的问题,请参考以下文章