根据答案here,只需要在头文件中定义方法以使其内联。所以我的问题是,为什么有inline
个关键字?
答案 0 :(得分:2)
例如,如果要在标题内定义自由函数(不是类的成员函数),则需要将其声明为inline
,否则将其包含在多个翻译单元中将导致ODR冲突。
通常的方法是在标头中声明函数并在单独编译的.cpp
文件中定义它。但是,在标题中将其定义为inline
函数允许包含它的每个翻译单元都有其定义,这使得该函数更容易实际内联;如果大量使用该功能,这一点很重要。
答案 1 :(得分:0)
inline
关键字的历史原因是较旧的C编译器不像优质的现代C和C ++编译器那样优化代码。因此,最初引入它是为了允许程序员指示对inline
函数的偏好(有效地将函数体直接插入调用者,这避免了与函数调用相关的开销)。由于无法保证编译器可以内联函数(例如,某些编译器只能内联某些类型的函数),因此inline
关键字是一个提示而不是指令。
inline
的另一个典型用法并不是随意的 - 如果在多个编译单元中定义了一个函数(例如因为包含的标题是#include
d不止一次),那么就离开{{1导致违反一个定义规则(因此在未定义的行为中)。 inline
是对编译器的指令(反过来可能向链接器发出指令)来解决这种偶然违反单定义规则的行为,并生成一个工作程序(例如,不会导致链接器抱怨多个定义) )。
至于为什么它仍然需要,在功能上,预处理器只进行文本替换...例如用包含标题的内容替换inline
指令。
让我们考虑两种情况。第一个有两个源文件(编译单元);
#include
和
#include "some_header"
//some other functions needed by the program, not pertinent here
其中 #include "some_header"
int main()
{
foo();
}
包含定义
some_header
然而,第二种情况省略了头文件(是的,人们这样做)并将第一个源文件作为
void foo() { /* whatever */ }
和第二个;
void foo() { /* whatever */ }
//some other functions needed by the program, not pertinent here
在这两种情况下,假设编译并链接在一起的两个编译单元。结果是违反了一个定义规则(实际上,由于多个定义的符号,通常会导致链接器错误)。
根据当前的语言规则(具体来说,预处理器只进行文本替换),这两个场景必须在功能上完全等效。如果一个方案是打印值 void foo() { /* whatever */ }
int main()
{
foo();
}
,那么另一个方案也是如此。如果有一个未定义的行为(就像这里的情况那样),那么另一个。
但是,为了讨论起见,我们要求一个函数如果在头文件中定义,就会神奇地内联。这两种情况中的代码将不再相同。头文件版本将具有已定义的行为(不违反一个定义规则),第二个将具有未定义的行为。
糟糕。我们刚刚打破了两种情景的等价性。这似乎并不多,但程序员实际上很难理解为什么一个版本链接而另一个版本没有。除了将代码移动到头文件中之外,他们无法解决这个问题。
这意味着,我们需要一些方法来使两个场景等效。这意味着代码中需要有一些东西使它们等效。输入42
关键字,并在其前面添加inline
的定义。
现在,好吧,有人可能会争辩说预处理器应该做一些更聪明的事情,即做简单的文本替换。但是,现在你正在滑坡。 C和C ++标准(最后)指定预处理器执行此操作。而改变这将引入一系列其他变化。无论这是否是一个好主意(并且,当然,有一些倡导完全从C ++中消除预处理器),这是一个更大的变化,对语言和程序员(对谁来说是好的)有很多分歧或者坏,可以依赖预处理器的行为。
答案 2 :(得分:-1)
简短回答。这不是必需的。编译器通常会忽略inline
关键字。
其他问题已经提供了更全面的答案,更不用说你所链接问题的第二个答案了。