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

C++ 一个定义规则-内联函数的多个定义,c++,c++11,C++,C++11,我正在阅读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 arg

我正在阅读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;
}
它按照规定运作。我可以有多个内联函数的定义

  • 非内联函数链接和内联函数链接之间的区别是什么
  • 链接器如何区分这两者

使函数内联可以做两件事(第二点与您的问题更相关):

  • 程序员建议编译器快速调用这个函数,可能是通过内联扩展。大致上,内联扩展类似于将内联函数视为宏,通过其主体的代码扩展对它的每个调用。这是一个建议-编译器可能不会(有时也不能)执行这样的各种优化

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


  • 这两件事同时发生并不是巧合。最常见的情况是,
    内联
    函数通过几个源文件出现在标题
    #include
    d中,可能是因为程序员希望请求快速内联扩展。不过,这需要翻译单元局部性规则,这样就不会出现链接器错误。

    他引用的话说,对象或非内联函数不能有多个定义。我必须不同意第2点:
    inline
    并不意味着范围是单个翻译单元。这就是
    静态
    的工作<代码>内联
    可以使用或不使用
    静态
    进行定义。如果同一内联函数位于多个翻译单元中,则ODR有一个特定的例外,只要它们都相同。另见。我同意@Piquan。内联不会使函数成为翻译单元的本地函数。它只是告诉链接器——不要抱怨多个定义——只选择一个,放弃其他的,并相信用户所有这些函数都有相同的定义。否则,当函数本地静态在头文件中定义时,它们将无法按预期工作。@换句话说,在两个翻译单元中具有不同签名的非静态内联表达式将导致ODR冲突错误。对吗?我会非常小心我的措辞。您描述的是ODR冲突,这是程序员的一个错误。在这种情况下,编译器不需要注意错误或发出错误消息。但它最终可能会做一些与你期望的不同的事情。(顺便说一句,如果签名相同,但定义不同,也会出现这种情况。)
    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(); }