[英]Why do class member functions defined outside the class (but in header file) have to be inlined?
I have read existing answers on the two meanings of inline, but I am still confused.我已经阅读了有关内联两种含义的现有答案,但我仍然感到困惑。
Let's assume we have the following header file:假设我们有以下头文件:
// myclass.h
#ifndef INCLUDED_MYCLASS
#define INCLUDED_MYCLASS
class MyClass
{
public:
void foo(); // declaration
};
inline void MyClass::foo()
{
// definition
}
#endif
Why does void foo()
which is defined outside the class in the file, have to be explicitly defined with inline
?为什么在文件中的类之外定义的
void foo()
必须用inline
显式定义?
It's because you defined MyClass::foo
in a header file.这是因为您在头文件中定义了
MyClass::foo
。 Or a bit more abstract, that definition will be present in multiple translation units (every .cpp file that includes the header).或者更抽象一点,该定义将出现在多个翻译单元中(每个包含标题的 .cpp 文件)。
Having more than one definition of a variable/function in a program is a violation of the one definition rule, which requires that there must be only one definition in a single program of every variable/function.在一个程序中对一个变量/函数有多个定义是违反一个定义规则的,它要求在一个程序中每个变量/函数必须只有一个定义。
Note that header guards do not protect against this, as they only protect if you include the same header multiple times in the same file.请注意,标头保护不能防止这种情况发生,因为它们仅在您在同一文件中多次包含相同标头时提供保护。
Marking the function definition as inline
though means that the definition will always be the same across multiple translation units.将函数定义标记为
inline
意味着定义在多个翻译单元中始终相同。 1 . 1 .
In practice, this means that the linker will just use the first definition of MyClass::foo
and use that everywhere, while ignoring the rest,实际上,这意味着链接器将只使用
MyClass::foo
的第一个定义并在任何地方使用它,而忽略其余部分,
1 : If this is not the case your program is ill-formed with no diagnostics required whatsoever. 1 : 如果不是这种情况,则您的程序格式错误,不需要任何诊断。
If you put MyClass::foo()
in a header file and fail to declare it inline
then the compiler will generate a function body for every compilation unit that #include
s the header and these will clash at link time.如果您将
MyClass::foo()
放在头文件中并且未能将其声明为inline
那么编译器将为每个包含#include
头文件的编译单元生成一个函数体,并且这些将在链接时发生冲突。 The usual error thrown by the linker is something along the lines of Multiple definition of symbol MyClass::foo()
or somesuch.链接器抛出的常见错误是
Multiple definition of symbol MyClass::foo()
的Multiple definition of symbol MyClass::foo()
或类似的东西。 Declaring the function inline
avoids this, and the compiler and linker have to be in cahoots about it.将函数声明为
inline
避免了这种情况,编译器和链接器必须对此进行协调。
As you mention in your comment, the inline
keyword also acts a hint to the compiler that you'd like the function to be actually inlined, because (presumably) you call it often and care more about speed than code size.正如您在评论中提到的,
inline
关键字还向编译器暗示您希望函数实际内联,因为(大概)您经常调用它并且更关心速度而不是代码大小。 The compiler is not required to honour this request though, so it might generate one or more function bodies (in different compilation units) which is why the linker has to know that they are actually all the same and that it only needs to keep one of them (any one will do).编译器不需要满足这个请求,所以它可能会生成一个或多个函数体(在不同的编译单元中),这就是为什么链接器必须知道它们实际上都是相同的,并且它只需要保留其中之一他们(任何人都会做)。 If it didn't know they were all the same then it wouldn't know what to do, which is why the 'classical' behaviour has always been to throw an error.
如果它不知道它们都是一样的,那么它就不知道该怎么做,这就是为什么“经典”行为总是抛出错误的原因。
Given that the compilers these days often inline small functions anyway, most compilers also have some kind of noinline
keyword but that is not part of the standard.鉴于
noinline
编译器无论如何经常内联小函数,大多数编译器也有某种noinline
关键字,但这不是标准的一部分。
More about inline
at cppreference .有关cppreference
inline
更多信息。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.