我正在阅读ODR,正如规则所说,我尝试了以下操作...
file1.cpp
#include <iostream>
using namespace std;
inline int func1(void){ return 5; }
inline int func2(void){ return 6; }
inline int func3(void){ return 7; }
int sum(void);
int main(int argc, char *argv[])
{
cout << func1() << endl;
cout << func2() << endl;
cout << func3() << endl;
cout << sum() << endl;
return 0;
}
字符串
file2.cpp
inline int func1(void) { return 5; }
inline int func2(void) { return 6; }
inline int func3(void) { return 7; }
int sum(void) { return func1() + func2() + func3(); }
型
它就像规则说的那样工作。我可以有多个内联函数的定义。
- 非内联函数链接和内联函数链接之间有什么区别?
- 链接器如何区分这两种情况?
2条答案
按热度按时间tpxzln5u1#
创建一个函数
inline
做了两件事(第二点与你的问题更相关):1.这是程序员对编译器的一个建议,可以通过内联扩展来快速调用这个函数。粗略地说,内联扩展类似于将内联函数当作宏处理,通过其主体的代码来扩展对它的每个调用。这是一个 * 建议 * -编译器可能不会(有时不能)执行这样的各种优化。
1.它将函数的作用域指定为转换单元的作用域。(或者因为它是写在它里面的,或者因为它
#include
是写在它里面的一个头,在这种情况下,预处理器基本上是这样做的)。现在编译foo.cpp
,还可能包含具有相同签名的inline
函数的其他bar.cpp
(可能是同一个;可能是由于两个#include
使用相同的头)。当链接器链接两个目标文件时,它不会被认为违反ODR,因为inline
指令使文件的每个副本都在其翻译单元(有效地通过编译它创建的目标文件)的本地。这不是一个建议,它是 * 绑定 *。这两件事结合在一起并不是巧合。最常见的情况是一个
inline
函数出现在几个源文件的头文件#include
d中,可能是因为程序员想要请求快速内联扩展。这需要执行单元局部性规则,这样就不会出现链接器错误。5hcedyr02#
非内联函数链接和内联函数链接之间有什么区别?
没有;请参见[dcl.inline]注解1
关键字
inline
对函数的链接没有影响。“然而,
inline
导致单一定义规则(ODR)的放松:对于具有多个转换单位中的定义的任何可定义项
D
,D
是一个非内联非模板化函数或变量,或者程序格式不正确; [...]
换句话说,一个内联函数可以在多个翻译单元(即
.cpp
文件)中定义,而不会出现链接器错误。这是因为链接器选择了一个定义,而忽略了所有其他定义。换句话说,一个内联函数是一个weak symbol。然而,[basic.def.odr]定义了大量的限制。也就是说,内联函数需要在任何地方都被定义为 * 完全 * 相同的,逐个标记的。例如:
字符串
这样的程序是错误的,不需要诊断,因为定义是不相同的。确保所有定义都相同的最简单的方法是将它们放在一个标题中。标题被复制并粘贴到
#include
的翻译单元中,这样就不太可能出错。另请参阅Why do inline functions have to be defined in a header file?“内联”怎么样?
编译器将内联函数作为优化,而不管是否使用
inline
。只要函数的定义对编译器可见,它就会执行此优化。inline
只是提供了一个提示,有助于启发式算法决定是否应该进行内联。