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