最小代码:
// --------inline.h--------
struct X {
static inline void foo ();
};
#ifdef YES
inline void X::foo () { cout << "YES\n"; }
#else
inline void X::foo () { cout << "NO\n"; }
#endif
// --------file1.cpp--------
#define YES // <----
#include"inline.h"
void fun1 ()
{
X::foo();
}
// --------file2.cpp--------
#include"inline.h"
void fun2 ()
{
X::foo();
}
如果我们拨打fun1()
和fun2()
,他们将分别打印YES
和NO
,这意味着他们指的是同一个X::foo()
的不同功能正文
无论是否应编码,我的问题是:
这是一个定义明确或未定义的行为吗?
答案 0 :(得分:13)
是的,这是未定义的行为。
<强>参考:强>
C ++ 03标准:
7.1.2函数说明符[dcl.fct.spec]
第4段:
内联函数应在每个使用它的翻译单元中定义,并且在每种情况下都应具有完全相同的定义(3.2)。 [注意:在定义出现在翻译单元之前,可能会遇到对内联函数的调用。 ]如果在一个翻译单元中内联声明具有外部链接的功能,则应在其出现的所有翻译单元中内联声明;无需诊断。一个 具有外部链接的内联函数在所有翻译单元中应具有相同的地址。外部内联函数中的静态局部变量始终引用同一个对象。 extern内联函数中的字符串文字是不同翻译单元中的相同对象。
注意:3.2指的是一个定义规则,其中规定:
3.2一个定义规则[basic.def.odr]
第1段:
任何翻译单元都不得包含任何变量,函数,类类型,枚举类型或模板的多个定义。
答案 1 :(得分:7)
未定义。您违反了ODR。
答案 2 :(得分:4)
你尝试过吗?具有不同的优化级别?如果我们调用fun1()和fun2(),那么它们将分别打印YES和NO,这意味着它们引用相同X :: foo()的不同函数体。
我得到YES和NO,YES和YES,或NO和NO取决于优化级别和编译对象呈现给链接器的顺序。
毋庸置疑,这是未定义的行为。