以下在 C 和/或 C++ 中是否合法?
void fn();
inline void fn()
{
/*Do something here*/
}
我担心的是,第一个声明看起来暗示该函数将被定义为非内联函数,但下面的定义毕竟将它变成了内联函数。
如果在这种情况下 C 和 C++ 之间存在差异,那么也很高兴知道这种差异。
是的。事实上,它可能更可取。来源: http: //www.parashift.com/c++-faq/inline-nonmember-fns.html
经验法则:声明告诉你如何调用一个函数并使用它的返回值。定义说明当你调用它时会发生什么。您可以在不修改调用方式的情况下将函数更改为内联和返回,因此它是定义的一部分是有道理的。(当然,什么是有意义的和什么是真的并不总是匹配的,所以这只是一个规则。)
仅当代码实际出现在头文件中时才可以,如图所示。inline
如果头文件包含非内联声明,但定义并未出现在所有翻译单元中,这将是未定义的行为(不需要诊断) ;即使没有调用该函数。
参考:C++14 [dcl.fct.spec]/4(注意定义也是声明):
如果具有外部链接的函数在一个翻译单元中声明为内联,则应在其出现的所有翻译单元中声明为内联;不需要诊断。
如果代码出现在类定义中,没关系,inline
关键字是多余的,因为出现在类定义中的函数定义是隐式的inline
。
如果包含类定义void fn();
,然后有一个 out-of-line definition inline void Class::fn() {
,则行为与非成员情况相同。
C11 6.7.4/7:
如果翻译单元中函数的所有文件范围声明都包含
inline
函数说明符 withoutextern
,则该翻译单元中的定义是内联定义。
非内联声明的存在意味着后面的定义不是内联定义,尽管它有inline
关键字。因此,该定义实际上是一个外部定义(即与未标记的链接属性相同inline
)。
因此,如果此代码出现在两个翻译单元包含的头文件中,则由于多个外部定义,这是未定义的行为;但如果原型在标题中并且定义在包含该标题的一个翻译单元中,则可以。
注意:GNU Cinline
与 ISO C 不同inline
。我不确定此代码在 GNU C 中的定义行为。
内联函数是编译器将函数定义中的代码直接复制到调用函数的代码中,而不是在内存中创建一组单独的指令。代替将控制权转移到函数代码段和从函数代码段转移,函数体的修改副本可以直接替换函数调用。这样就避免了函数调用的性能开销。
C任何函数,除了 main 之外,都可以使用 inline 函数说明符声明或定义为内联。不允许在内联函数体内定义静态局部变量。
在类声明中实现的C++函数是自动内联定义的。在类声明之外声明的常规 C++ 函数和成员函数(main 除外)可以使用 inline 函数说明符声明或定义为内联。在内联函数的主体中定义的静态局部变量和字符串文字在翻译单元中被视为相同的对象。
结论
C++
类:您的两个函数本质上具有相同的原型。然而,由于第一个函数将嵌入到一个类中,它与定义的内联函数处于不同的范围内。这样就可以了。
非类:如果你没有在类中嵌入非内联函数,它将被视为重新定义错误并给出编译错误。因为它期望重载但原型是相同的。
C
C 与非类的 C++ 变体相同。因此,如果您像在 .c 文件中的问题中那样定义它,编译器将向您抛出重新定义错误。喜欢:
redefinition of 'fn
和/或注释:
previous definition of 'fn' was here