如果它编译,这样的事情将明显违反 C++ 单一定义规则:
// Case 1
// something.h
struct S {};
struct A
{
static const S val = S();
};
因为如果 something.h 包含在多个模块中,A::val
则会重复定义。但是,这是允许的:
// Case 2
// someOtherThing.h
struct B
{
static const int val = 3;
};
据我了解,这种情况可以的原因是因为B::val
它是一个整数类型的编译时常量,所以编译器基本上可以B::val
用文字对所有引用进行搜索和替换3
(反汇编的检查表明了这一点正是它的作用)。因此,在某种意义上,最终产品中的定义为零B::val
,因此 ODR 不适用。但是,考虑一下:
// Case 3
// yetAnotherThing.h
struct C
{
static const int val = 3;
const int* F()
{
return &val;
}
};
这是允许的,反汇编表明在这种情况下,实际上已经预留了一些内存位置来存储 的值C::val
。从表面上看,这意味着如果 yetAnotherThing.h 包含在多个模块中,我们现在就违反了 ODR,因为static const int val = 3
现在会导致存储被“发射”。然而编译器和链接器(VC++2012)都没有抱怨。
为什么?这只是编译器/链接器的作者必须处理的令人讨厌的特殊情况吗?如果是这样,为什么不能使用相同的系统来使案例 #1 也可以工作?
(欢迎引用标准中的相关引用,但它们不一定能回答问题。如果标准说pink_elephants
关键字的任何使用都应该导致数字 42 的每个实例都被替换为 666,那么就是这样,但我们'仍然会想知道为什么存在这样一个奇怪的规则。)