一个定义规则 - 内联函数的多个定义

NJM*_*JMR 8 c++ c++11

我正在阅读ODR,正如规则所说"In the entire program, an object or non-inline function cannot have more than one definition",我尝试了以下内容......

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;
}
Run Code Online (Sandbox Code Playgroud)

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(); }
Run Code Online (Sandbox Code Playgroud)

按规则说,它起作用了.我可以有多个内联函数的定义.

  • 非内联函数链接和内联函数链接有什么区别?
  • 链接器如何区分这两者?

Ami*_*ory 9

使函数inline做两件事(第二点与你的问题更相关):

  1. 程序员建议编译器快速调用此函数,可能是通过内联扩展.粗略地说,内联扩展类似于将内联函数视为宏,通过其主体代码扩展每个调用.这是一个建议 - 编译器可能不会(有时不能)执行这样的各种优化.

  2. 它指定函数的范围是翻译单元的范围.因此,如果inline函数出现在foo.cpp(因为它是在其中写入,或者因为它#include是在其中写入的标题,在这种情况下,预处理器基本上就是这样).现在你编译foo.cpp,也可能还有一些其他的bar.cpp也包含一个inline具有相同签名的函数(可能是完全相同的一个;可能是由于两个#include相同的头).当链接器链接两个目标文件时,它不会被视为违反ODR,因为该inline指令使文件的每个副本都在其翻译单元本地(通过有效编译它创建的目标文件).这不是一个建议,它具有约束力.

将这两件事放在一起并非巧合.最常见的情况是inline函数出现在头文件#included中的几个源文件,可能是因为程序员想要请求快速内联扩展.但是,这需要转换单元位置规则,因此不应出现链接器错误.

  • 我必须不同意第2点:"内联"并不意味着范围是一个单一的翻译单位.这是"静态"的工作.`inline`可以使用或不使用`static`来定义.如果相同的内联函数位于多个翻译单元中,则ODR有一个特定的例外,只要它们完全相同即可.另见http://en.cppreference.com/w/cpp/language/inline. (3认同)