考虑以下示例:
// usedclass1.hpp
#include <iostream>
class UsedClass
{
public:
UsedClass() { }
void doit() { std::cout << "UsedClass 1 (" << this << ") doit hit" << std::endl; }
};
// usedclass2.hpp
#include <iostream>
class UsedClass
{
public:
UsedClass() { }
void doit() { std::cout << "UsedClass 2 (" << this << ") doit hit" << std::endl; }
};
// object.hpp
class Object
{
public:
Object();
};
// object.cpp
#include "object.hpp"
#include "usedclass2.hpp"
Object::Object()
{
UsedClass b;
b.doit();
}
// main.cpp
#include "usedclass1.hpp"
#include "object.hpp"
int main()
{
Object obj;
UsedClass a;
a.doit();
}
代码编译时没有任何编译器或链接器错误。但输出对我来说很奇怪:
Fedora x86_64 上的 gcc (Red Hat 4.6.1-9) 没有优化 [ EG1 ]:
UsedClass 1 (0x7fff0be4a6ff) doit hit
UsedClass 1 (0x7fff0be4a72e) doit hit与 [EG1] 相同,但启用了 -O2 选项 [ EG2 ]:
UsedClass 2 (0x7fffcef79fcf) doit 命中
UsedClass 1 (0x7fffcef79fff) doit 命中Windows XP 32bit 上的 msvc2005 (14.00.50727.762) 没有优化 [ EG3 ]:
UsedClass 1 (0012FF5B) doit 命中
UsedClass 1 (0012FF67) doit 命中与 [EG3] 相同,但启用了 /O2(或 /Ox)[ EG4 ]:
UsedClass 1 (0012FF73) doit 命中
UsedClass 1 (0012FF7F) doit 命中
我期望链接器错误(假设违反了 ODR 规则)或 [EG2] 中的输出(内联代码,没有从翻译单元导出任何内容,保留 ODR 规则)。因此我的问题:
- 为什么输出 [EG1]、[EG3]、[EG4] 可能?
- 为什么我从不同的编译器甚至从同一个编译器得到不同的结果?这让我认为标准在这种情况下没有指定行为。
感谢您的任何建议、意见和标准解释。
更新
我想了解编译器的行为。更准确地说,如果违反了 ODR,为什么不会产生错误。一个假设是,由于UsedClass1和UsedClass2类中的所有函数都被标记为内联(因此不违反 C++03 3.2),因此链接器不会报告错误,但在这种情况下会输出 [EG1]、[EG3]、[ EG4] 看起来很奇怪。