TEST.CPP
#include <iostream>
void f()
{
std::cout<<"non-inline"<<std::endl;
}
的main.cpp
#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 ++中的函数提供外部定义?
THX !!
答案 0 :(得分:6)
您的程序具有UB(未定义行为),因为它通过提供f()
的两个不同定义来违反ODR(一个定义规则)。因此,接下来无法推断为什么它会以某种方式运行。在UB的最佳传统中,任何行为都是可能的(包括通过互联网订购披萨)。
修改强>
标准(ISO / IEC 14882:2011)中的这些引用证明它是UB:
[basic.def.odr]§3:
每个程序应该只包含该程序中使用的每个非内联函数或变量的一个定义;无需诊断。 ......内联函数应在每个使用它的翻译单元中定义。
[basic.def.odr]§5:
可以有多个内联函数的定义 外部联系......在一个程序中提供了每个定义 出现在不同的翻译单元中,并提供了定义 满足以下要求。鉴于这样一个名为D的实体 在多个翻译单元中定义,然后
- D的每个定义应由相同的令牌序列组成;和
- ...
[dcl.fct.spec]§4
内联函数应在每个使用过的翻译单元中定义,并且在每种情况下都应具有完全相同的定义(3.2)。 [注意:在定义出现在翻译单元之前,可能会遇到对内联函数的调用。 -end note ]如果函数的定义在第一次声明为内联之前出现在翻译单元中,则该程序格式错误。 如果在一个翻译单元中内联声明具有外部链接的函数,则应在其出现的所有翻译单元中内联声明;无需诊断。 ......
(强调我的)
答案 1 :(得分:6)
您的程序违反One definition Rule,然后是Undefined behavior。
当你有一个未定义的行为时,一切皆有可能,但你必须知道在最重要的演示期间最坏的情况会发生;)
标准说:
3.2一个定义规则[basic.def.odr]
1 /翻译单元不得包含任何变量,函数,类类型,枚举类型或模板的多个定义。
<强> [...] 强>
4 /每个程序应包含该程序中每个非内联函数或变量的一个定义;无需诊断。该定义可以在程序中明确显示,可以在标准或用户定义的库中找到,或者(在适当的时候)隐式定义(见12.1,12.4和12.8)。 内联函数应在每个使用它的翻译单元中定义。
5 / [...]内联函数的定义不止一个,外部链接(7.1.2)[...]在一个程序中,只要每个定义出现在不同的翻译单元中,并提供定义满足以下要求。鉴于在多个翻译单元中定义了这样一个名为D的实体,那么
D的每个定义应由相同的令牌序列组成;以及
[...]
如果D的定义满足所有这些要求,那么程序应该表现得就像D的单个定义一样。如果D的定义不满足这些要求,那么行为是不确定的。强>
后来:
7.1.2函数说明符[dcl.fct.spec]
4 / 内联函数应在每个使用过的翻译单元中定义,并且在每种情况下都应具有完全相同的定义(3.2)。 [注意:在定义出现在翻译单元之前,可能会遇到对内联函数的调用。 - endnote ] 如果函数的定义在第一次声明为内联之前出现在翻译单元中,则程序格式不正确。如果声明了具有外部链接的函数在一个翻译单元中内联,应在其出现的所有翻译单元中内联声明;无需诊断。