在函数之前使用inline关键字和在标题中声明整个函数之间的区别是什么?
所以...
int whatever() { return 4; }
VS
·H:
inline int whatever();
的.cpp:
inline int myClass::whatever()
{
return 4;
}
就此而言,这是做什么的:
inline int whatever() { return 4; }
答案 0 :(得分:29)
有几个方面:
<强>语言强>
inline
关键字标记时,它的定义应该在TU中可用,或者程序格式错误。inline
。inline
(隐式或显式)的函数可以在多个TU中定义(关于ODR),而常规函数则不是这样。inline
个相同的处理。编译器行为
inline
的函数将在每个目标文件中作为弱符号发出,这可能会增加它们的大小(查找模板膨胀)。链接器行为
答案 1 :(得分:10)
没有 inline
,如果函数在命名空间或全局范围内声明,则可能最终会出现多个导出符号(导致链接器错误) )。
但是,对于一个类(如您的示例所示),大多数编译器隐式将该方法声明为内联(-fno-default-inline
将在GCC上禁用该默认值。)
如果将函数声明为内联函数,编译器可能希望在转换中看到它的定义。因此,您应该在定义可见的时候保留它。
在更高级别:更多翻译经常可以看到类声明中的定义。这可以带来更好的优化,并且可以增加编译时间。
除非手动优化和快速编译都很重要,否则最近在类声明中使用关键字是不常见的。
答案 2 :(得分:9)
inline
的目的是允许在多个翻译单元中定义函数,这对于某些编译器能够在任何使用它的地方内联它是必要的。它应该在头文件中定义函数时使用,尽管在定义模板或类定义中的函数时可以省略它。
在没有inline
的标题中定义它是一个非常糟糕的主意;如果你包含多个翻译单元的标题,那么你就打破了一个定义规则;您的代码可能不会链接,如果有,可能会显示未定义的行为。
在inline
的标题中声明它但在源文件中定义它也是一个非常糟糕的主意;该定义必须在使用它的任何翻译单元中可用,但通过在源文件中定义它,它只能在一个翻译单元中使用。如果另一个源文件包含标题并尝试调用该函数,则您的程序无效。
答案 3 :(得分:3)
此问题解释了很多内联函数What does __inline__ mean ?(即使它是关于内联关键字。)
基本上,它与标题无关。在标题中声明整个函数只会更改函数源所在的源文件.Inline关键字会修改生成的编译函数的放置位置 - 在它自己的位置,以便每次调用将去那里,或代替每次通话(更好的表现)。但是,编译器有时会选择为自己内联的函数或方法,关键字只是编译器的建议。即使是内联未指定的函数,编译器也可以选择内联函数,如果这样可以提供更好的性能。
答案 4 :(得分:1)
如果要将多个对象链接到可执行文件中,通常应该只有一个对象包含该函数的定义。对于int whatever() { return 4; }
- 用于生成对象的任何翻译单元将包含whatever
函数的定义(即可执行代码)。链接器将不知道将哪个指向呼叫者。如果提供了inline
,则可执行代码可能会或可能不会在调用站点内联,但如果不是,则允许链接器假定所有定义都相同,并且任意选择一个以将调用者指向。如果不知何故定义不一样,那么它被认为是你的错,你会得到未定义的行为。要使用inline
,在编译调用时必须知道定义,因此,如果所有调用者恰好在以后的所有调用者中,那么将内联声明放在标题中以及内联定义放在.cpp文件中的想法将起作用。相同的.cpp文件 - 通常它已经坏了,你希望(名义上)内联函数的定义出现在声明它的标题中(或者没有事先声明就有一个单独的定义)。