TEST.CPP
#include <iostream>
void f()
{
std::cout<<"non-inline"<<std::endl;
}
Run Code Online (Sandbox Code Playgroud)
main.cpp中
#include <iostream>
using namespace std;
inline void f()
{
cout<<"inline"<<endl;
}
int main()
{
f();
return 0;
}
Run Code Online (Sandbox Code Playgroud)
在调试模式下,输出为:非内联.命令:g ++ [-g] -o main main.cpp test.cpp
在发布模式下,输出为:内联.命令:g ++ -O -o main main.cpp test.cpp
为什么?
Linux G ++ 4.7.3
在C99中,内联定义不提供函数的外部定义,因此我们可以通过在其他源文件中定义另一个函数来提供标识符的外部定义.
内联定义是否为C++中的函数提供了外部定义?
谢谢!!
您的程序具有UB(未定义行为),因为它通过提供两个不同的定义来违反ODR(一个定义规则)f().因此,接下来无法推断为什么它会以某种方式运行.在UB的最佳传统中,任何行为都是可能的(包括通过互联网订购披萨).
编辑
标准(ISO/IEC 14882:2011)中的这些引用证明它是UB:
[basic.def.odr]§3:
每个程序应该只包含该程序中使用的每个非内联函数或变量的一个定义; 无需诊断.......内联函数应在每个使用它的翻译单元中定义.
[basic.def.odr]§5:
对于具有外部链接的...内联函数,可以有多个定义...在程序中,每个定义出现在不同的翻译单元中,并且定义满足以下要求.鉴于这样一个名为D的实体在多个翻译单元中定义,那么
- D的每个定义应由相同的令牌序列组成; 和
- ...
[dcl.fct.spec]§4
内联函数应在每个使用过的翻译单元中定义,并且在每种情况下都应具有完全相同的定义(3.2).[ 注意:在定义出现在翻译单元之前,可能会遇到对内联函数的调用.-end note ]如果函数的定义在第一次声明为内联之前出现在翻译单元中,则程序格式错误.如果在一个翻译单元中内联声明具有外部链接的功能,则应在其出现的所有翻译单元中内联声明; 无需诊断....
(强调我的)
如果你有一个未定义的行为,一切皆有可能,但你必须知道在最重要的演示期间最坏的情况会发生;)
标准说:
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).[ 注意:在定义出现在翻译单元之前,可能会遇到对内联函数的调用.- 尾注 ] 如果函数的定义在第一次声明为内联之前出现在翻译单元中,则该程序格式不正确.如果在一个翻译单元中内联声明具有外部链接的功能,则应在其出现的所有翻译单元中内联声明; 无需诊断.
| 归档时间: |
|
| 查看次数: |
112 次 |
| 最近记录: |