为什么以下代码会生成这样的输出?
main.cpp ctor 0x24a4c30
test.cpp dtor 0x24a4c30
TEST.CPP
#include <boost/optional.hpp>
struct Test
{
Test()
{
printf("test.cpp ctor %p\n", (void *) this);
}
~Test()
{
printf("test.cpp dtor %p\n", (void *) this);
}
};
boost::optional< Test > t;
的main.cpp
#include <memory>
struct Test
{
Test()
{
printf("main.cpp ctor %p\n", (void *) this);
}
~Test()
{
printf("main.cpp dtor %p\n", (void *) this);
}
};
int
main(void)
{
std::make_shared< Test >();
return 0;
}
使用
编译g++ -std=c++11 -c test.cpp -o test.o
g++ -std=c++11 -c main.cpp -o main.o
g++ -std=c++11 test.o main.o
我解释了 test.o 提供Test的 ctor&amp; dtor 然后链接器会丢弃来自 main.o 的重复符号,但它仅适用于 dtor 。如果我删除静态对象 t ,则链接器会丢弃来自 test.o 的符号,然后输出
main.cpp ctor 0x208ec30
main.cpp dtor 0x208ec30
答案 0 :(得分:0)
如评论中所述,在两个链接的翻译单元中定义相同的符号会违反One Definition Rule,而
程序中可以有多个定义,只要每个定义 定义出现在每个的不同翻译单元中 以下:类类型,枚举类型,内联函数与外部 链接,内联变量与外部链接(自C ++ 17),类 模板,非静态函数模板,类的静态数据成员 模板,类模板的成员函数,部分模板 专业化,概念(自C ++ 20以来)只要以下所有内容 是的:
- 每个定义包含相同的令牌序列(通常显示在同一个头文件中)
- [...]
如果满足所有这些要求,程序就像是一样 整个程序中只有一个定义。否则, 行为未定义。 (强调我的)
UB的观察结果不需要解释,也可能没有。
当然,这是一种公然的违规行为。但是,在更无辜的程序中,可能会出现一种非常类似的情况(并导致奇怪且难以找到错误)。例如,在某些类声明更改时链接旧的单独编译的对象。