内联关键字与标头定义
Inline keyword vs header definition
函数之前使用内联关键字和只在标头中声明整个函数有什么区别?
所以。。。
int whatever() { return 4; }
与
.h:
inline int whatever();
。.cpp:
inline int myClass::whatever()
{
return 4;
}
就此而言,这有什么作用:
inline int whatever() { return 4; }
有几个方面:
语言
- 当一个函数被标记为
inline
关键字时,它的定义应该在 TU 中可用,或者程序格式不正确。 - 在类定义中定义的任何函数都隐式标记为
inline
。 - 标记为
inline
(隐式或显式)的函数可以在多个 TU(遵守 ODR)中定义,而常规函数则不是这种情况。 - 模板函数(不完全专用)得到与
inline
函数相同的处理。
编译器行为
- 标记为
inline
的函数将在必要时作为弱符号在每个对象文件中发出,这可能会增加它们的大小(查找模板膨胀)。 - 而编译器实际内联调用(即,在使用点复制/粘贴代码而不是执行常规函数调用)完全由编译器自行决定。关键字的存在可能会影响决策,但充其量只是一个提示。
链接器行为
- 弱符号合并在一起,在最终库中出现一次。一个好的链接器可以检查多个定义是否一致,但这不是必需的。
如果没有inline
,如果函数是在命名空间或全局范围内声明的,则最终可能会得到多个导出的符号(导致链接器错误)。
但是,对于一个类(如示例中所示),大多数编译器将该方法隐式声明为内联(-fno-default-inline
将在 GCC 上禁用该默认值)。
如果将函数声明为内联函数,编译器可能希望在翻译中看到其定义。 因此,应将其保留到定义可见的时间。
在更高级别:类声明中的定义通常对更多翻译可见。 这可以带来更好的优化,并可能导致编译时间增加。
除非手动优化和快速编译都很重要,否则现在在类声明中使用关键字是不寻常的。
inline
的目的是允许在多个翻译单元中定义函数,这对于某些编译器能够在使用任何地方内联它是必需的。每当在头文件中定义函数时都应使用它,尽管在定义模板或类定义中的函数时可以省略它。
在没有inline
的情况下在标头中定义它是一个非常糟糕的主意;如果包含来自多个翻译单元的标头,那么您违反了一个定义规则;您的代码可能不会链接,并且如果链接链接,可能会表现出未定义的行为。
带有inline
的标头中声明它,但在源文件中定义它也是一个非常糟糕的主意;定义必须在使用它的任何翻译单元中可用,但是通过在源文件中定义它,它只能在一个翻译单元中使用。如果另一个源文件包含标头并尝试调用该函数,则您的程序无效。
这个问题解释了很多关于内联函数的信息 __inline__是什么意思?(即使它是关于内联关键字的。
基本上,它与标题无关。在标头中声明整个函数只会更改函数源所在的源文件。Inline 关键字修改生成的编译函数的放置位置 - 在它自己的位置,以便每个调用都会去那里,或者代替每个调用(对性能更好)。但是,编译器有时会选择为自己内联哪些函数或方法,关键字只是对编译器的建议。即使未以内联方式指定的函数也可以由编译器选择内联,如果这样可以提供更好的性能。
如果要将多个对象链接到可执行文件中,通常应该只有一个对象包含函数的定义。 对于int whatever() { return 4; }
- 用于生成对象的任何翻译单元都将包含whatever
函数的定义(即可执行代码)。 链接器不知道将调用方定向到哪一个。 如果提供了inline
,则可执行代码可能会也可能不会在调用站点内联,但如果不是,则允许链接器假定所有定义都相同,并任意选择一个以将调用方定向到。 如果定义不尽相同,那么它被认为是你的错,你会得到未定义的行为。 要使用inline
,在编译器调用时必须知道定义,因此您将内联声明放在标头中并将内联定义放在.cpp文件中的想法只有在所有调用者碰巧在同一个.cpp文件中时才有效 - 一般来说它是坏的,并且您希望(名义上)内联函数的定义出现在声明它的标头中(或者有一个定义,无需事先声明)。
- 如何确保C++函数在定义之前声明(如override关键字)
- 在 c++ 中正确定义"this"关键字?
- 只要我不包含一个标题,重新定义C++关键字合法吗
- 如何使用 "using" 关键字定义函数原型/签名
- 设置自定义收集器时不会提升::log尊重关键字::max_size吗?
- 如何添加自定义关键字以 clang 格式被视为"class"?
- 为什么静态成员函数定义不能有关键字"static"?
- C++ 包含中的"未定义"模块关键字
- C++不使用"inline"或"static"无类函数的关键字时出现重定义链接错误
- 虚拟关键字的使用与C++中的简单重新定义
- 在构造函数中使用关键字 "this" 时定义复制构造函数
- 我应该在源文件之间共享的常量的定义中添加关键字"extern"吗
- 如果我返回const定义的对象,为什么const关键字被取消资格
- 如果我在标题文件中使用关键字的声明,则应该在定义本身中包含相同的关键字
- 具有多个定义时,对于外部关键字没有错误
- C++:定义类函数的.cpp文件中实例本身的表示关键字
- 为什么我应该使用"typename"关键字来定义?
- VIM 注释中的自定义关键字突出显示
- 如何制作自定义关键字语句
- 未定义关键字"and"、"or"和"not"