0

测试.cpp

#include <iostream>
void f()
{
    std::cout<<"non-inline"<<std::endl;
}

主文件

#include <iostream>
using namespace std;
inline void f()
{
    cout<<"inline"<<endl;
}

int main()
{
    f();
    return 0;
}

在调试模式下,输出为:非内联。命令:g++ [-g] -o main main.cpp test.cpp

在发布模式下,输出为:inline。命令:g++ -O -o main main.cpp test.cpp

为什么?

Linux G++ 4.7.3

在 C99 中,内联定义不为函数提供外部定义,因此我们可以通过在其他源文件中定义另一个函数来提供标识符的外部定义。

内联定义是否为 C++ 中的函数提供外部定义?

谢谢!!

4

2 回答 2

6

您的程序具有 UB(未定义行为),因为它通过提供两种不同的f(). 因此,几乎没有办法推理为什么它会以一种或另一种方式表现。在 UB 的最佳传统中,任何行为都是可能的(包括通过 Internet 订购披萨)。

编辑

这些来自标准 (ISO/IEC 14882:2011) 的引用证明它是 UB:

[basic.def.odr]§3:

每个程序都应包含该程序中 odr 使用的每个非内联函数或变量的准确定义;无需诊断。...内联函数应在使用它的每个翻译单元中定义。

[basic.def.odr]§5:

如果每个定义出现在不同的翻译单元中,并且定义满足以下要求,则程序中可以有多个定义...具有外部链接的内联函数...。给定这样一个名为 D 的实体在多个翻译单元中定义,则

  • D 的每个定义都应由相同的记号序列组成;和
  • ...

[dcl.fct.spec]§4

内联函数应在使用它的每个翻译单元中定义,并且在每种情况下都应具有完全相同的定义(3.2)。[注意:在其定义出现在翻译单元中之前,可能会遇到对内联函数的调用。-end note ] 如果函数的定义在其第一次声明为 inline 之前出现在翻译单元中,则程序格式错误。如果具有外部链接的函数在一个翻译单元中声明为内联,则应在其出现的所有翻译单元中声明为内联;不需要诊断。...

(强调我的)

于 2013-09-05T06:39:51.243 回答
6

你的程序违反了一个定义规则,那么它就是未定义的行为

当您有未定义的行为时,一切皆有可能,但您必须知道最重要的演示期间会出现最坏的情况;)

标准说:

3.2 一个定义规则[basic.def.odr]

1/ 任何翻译单元不得包含任何变量、函数、类类型、枚举类型或模板的多个定义。

[...]

4/ 每个程序都应包含该程序中 odr 使用的每个非内联函数或变量的准确定义;无需诊断。定义可以显式出现在程序中,可以在标准或用户定义库中找到,或者(在适当时)隐式定义(参见 12.1、12.4 和 12.8)。内联函数应在使用它的每个翻译单元中定义。

5/ 如果每个定义出现在不同的翻译单元中,并且定义满足以下要求。给定这样一个名为 D 的实体在多个翻译单元中定义,则

  • D 的每个定义都应由相同的记号序列组成;和

  • [...]

如果 D 的定义满足所有这些要求,那么程序的行为就好像有一个 D 的定义。如果 D 的定义不满足这些要求,那么行为是未定义的。

然后:

7.1.2 函数说明符 [dcl.fct.spec]

4/内联函数应在使用 odr 的每个翻译单元中定义,并且在每种情况下都应具有完全相同的定义(3.2)。[注意:在其定义出现在翻译单元中之前,可能会遇到对内联函数的调用。—<em>尾注]如果一个函数的定义在其第一次声明为内联之前出现在翻译单元中,则该程序是非良构的。如果具有外部链接的函数在一个翻译单元中声明为内联,则应在其出现的所有翻译单元中声明为内联;不需要诊断。

于 2013-09-05T06:42:29.897 回答