当我有以下代码A.cpp
并且 B.cpp
没有生成警告或错误,但是Initializer::Initializer()
inB.cpp
被调用两次而 inA.cpp
没有被调用时。
static int x = 0;
struct Initializer
{
Initializer()
{
x = 10;
}
};
static Initializer init;
由于这违反了一个定义规则并导致未定义的行为,我认为这是完全正常的。但是,当我将构造函数定义移到一个或两个文件中的类声明之外时,如下所示:
static int x = 0;
struct Initializer
{
Initializer();
};
Initializer::Initializer()
{
x = 10;
}
static Initializer init;
链接器突然变得足够聪明,可以出错并说one or more multiply defined symbols found
. 这里发生了什么变化,为什么这很重要?我原以为链接器应该始终能够检测到 ODR 损坏 - 什么情况下它不能检测到?
如果我错了,有人纠正我,但我的理论是,当你有模板化代码(定义总是在标题中)时,你最终会在许多编译单元中得到重复的定义。它们碰巧都是相同的,因此链接器是否只选择一个并孤立其他无关紧要,但不会出错,有多个定义或模板不起作用。