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++ 内联函数:这样声明,这样定义,还是两者兼而有之?为啥?的主要内容,如果未能解决你的问题,请参考以下文章

内联函数对作用

内联函数

复习笔记——C++内联函数

内联函数分析

7 类-内联函数

评论接口、实现还是两者兼而有之?