为内联函数定义多次,怎么可能?
Defined multiple times for the inline function, how possible?
以下引自 C++ 入门书的引述让我很困惑
Unlike other function, inline and constexpr functions may be defined
multiple times in the program. After all, the compiler needs the
definition, not just the declaration, in order to expand the code.
However, all of the definitions of a given inline or constexpr must
match exactly. As a result, inline and constexpr functions normally
are defined in headers.
-- C++ primer 5th Ed, 240 pp
"may be defined multiple times in the program" 这句话让我很困惑。据我了解,声明可以多次进行,但定义只需要一次。
谁能给我一个例子,为什么会有多重定义。
在头文件中(我们称它为 foo.h
)你可以有
inline int foo() { /* do stuff */ }
现在,如果您将 foo.h
包含在几个 cpp 文件中,那么 foo
将在每个文件中定义,这将是一个多重定义错误。尽管 foo
被标记为 inline
,但没关系,因为所有定义都是相同的。
As far as I understand, declaration can be made multiple time, but definition is only needed once
编译器在翻译单元(基本上是一个 cpp 文件)上工作,它可以在其中进行各种优化,但函数内联和 constexpr
要求编译器知道函数的定义。这意味着每个翻译单元都需要其中的函数定义。我们使用 inline 来解决这个问题,否则会出现多重定义错误。
我认为问题在于我们可以通过 "define." 表示多种含义 当您在头文件中编写内联函数时,它 "defined" 只是一次,因为只有在您的源代码中使用该名称的单个函数。
但这不是编译器和链接器看待世界的方式。如果您在从 a.cpp
和 b.cpp
调用的头文件中有一个内联函数 foo
,那么该函数的完整编译版本将包含在 a.obj
和 b.obj
。链接器通过仅选择其中一个编译版本来包含在您的最终二进制文件中来解决问题。
请注意,我在这里掩饰了重要的细节,但这是一般的想法(我认为你的教科书正在回避)。
举个例子。此版本无效。
// main.cpp
inline int square(int num) {
return num * num;
}
inline int square(int num) {
return num * num;
}
int main()
{
return square(2);
}
但是当你在多个 .cpp
文件(又名翻译单元)中拥有它时,没关系,因为现在 link 做正确的事是你的工作。
// b.cpp
inline int square(int num) {
return num * num;
}
// main.cpp
inline int square(int num) {
return num * num;
}
int main()
{
return square(2);
}
构建:gcc main.cpp b.cpp
同样的方法 #include
它会将代码放在那些 .cpp
文件中。
当然,如果函数体是 内联 ,那么 link 就没什么问题了 :)
如果编译器决定执行外联版本,您最终会得到多个目标文件 (.o
),其中定义了相同的 "inline" 函数。这样的定义会被标记出来。
多亏了那个标记 linker 不会放弃它已经找到了多个定义,而只是选择它找到的第一个。
所以如果所有的定义真的一样,那很好!如果我们有不同的这种功能,我们就会遇到麻烦。文件 b.cpp
中的示例
// b.cpp
inline int square(int num) {
return 1;
}
同一内联函数有多个不同的定义是未定义的行为。它当然会编译,但我们得到了什么?这取决于 linker 的选择 :D
以下引自 C++ 入门书的引述让我很困惑
Unlike other function, inline and constexpr functions may be defined multiple times in the program. After all, the compiler needs the definition, not just the declaration, in order to expand the code. However, all of the definitions of a given inline or constexpr must match exactly. As a result, inline and constexpr functions normally are defined in headers. -- C++ primer 5th Ed, 240 pp
"may be defined multiple times in the program" 这句话让我很困惑。据我了解,声明可以多次进行,但定义只需要一次。
谁能给我一个例子,为什么会有多重定义。
在头文件中(我们称它为 foo.h
)你可以有
inline int foo() { /* do stuff */ }
现在,如果您将 foo.h
包含在几个 cpp 文件中,那么 foo
将在每个文件中定义,这将是一个多重定义错误。尽管 foo
被标记为 inline
,但没关系,因为所有定义都是相同的。
As far as I understand, declaration can be made multiple time, but definition is only needed once
编译器在翻译单元(基本上是一个 cpp 文件)上工作,它可以在其中进行各种优化,但函数内联和 constexpr
要求编译器知道函数的定义。这意味着每个翻译单元都需要其中的函数定义。我们使用 inline 来解决这个问题,否则会出现多重定义错误。
我认为问题在于我们可以通过 "define." 表示多种含义 当您在头文件中编写内联函数时,它 "defined" 只是一次,因为只有在您的源代码中使用该名称的单个函数。
但这不是编译器和链接器看待世界的方式。如果您在从 a.cpp
和 b.cpp
调用的头文件中有一个内联函数 foo
,那么该函数的完整编译版本将包含在 a.obj
和 b.obj
。链接器通过仅选择其中一个编译版本来包含在您的最终二进制文件中来解决问题。
请注意,我在这里掩饰了重要的细节,但这是一般的想法(我认为你的教科书正在回避)。
举个例子。此版本无效。
// main.cpp
inline int square(int num) {
return num * num;
}
inline int square(int num) {
return num * num;
}
int main()
{
return square(2);
}
但是当你在多个 .cpp
文件(又名翻译单元)中拥有它时,没关系,因为现在 link 做正确的事是你的工作。
// b.cpp
inline int square(int num) {
return num * num;
}
// main.cpp
inline int square(int num) {
return num * num;
}
int main()
{
return square(2);
}
构建:gcc main.cpp b.cpp
同样的方法 #include
它会将代码放在那些 .cpp
文件中。
当然,如果函数体是 内联 ,那么 link 就没什么问题了 :)
如果编译器决定执行外联版本,您最终会得到多个目标文件 (.o
),其中定义了相同的 "inline" 函数。这样的定义会被标记出来。
多亏了那个标记 linker 不会放弃它已经找到了多个定义,而只是选择它找到的第一个。
所以如果所有的定义真的一样,那很好!如果我们有不同的这种功能,我们就会遇到麻烦。文件 b.cpp
// b.cpp
inline int square(int num) {
return 1;
}
同一内联函数有多个不同的定义是未定义的行为。它当然会编译,但我们得到了什么?这取决于 linker 的选择 :D