假设我有一个人为的头文件,其中包含一个模板类和两个源文件,其中包含完全相同的模板类实例,以及一个重复的函数。那是......
Contrived header(thing.hpp):
#pragma once
template <typename T>
class Thing {
public:
T t;
public:
T& value() {
return t;
}
};
thing.cpp:
#include <thing.hpp>
template class Thing<int>;
int MeaningOfLife() {
return 42;
}
thingy.cpp :(与thing.cpp完全相同)
编译和链接(在OS X上使用clang)时,似乎只有MeaningOfLife
被视为重复符号,但模板实例化的符号(仅Thing::value()
)不是。仔细检查反汇编后,似乎汇编指令被放置在名为Thing::value()
的{{1}}符号上。
问题0:这意味着该指令正在采取措施防止符号被多重定义,但它究竟在做什么?
问题1:其他编译器可以在其他地方(例如Linux,Windows等)进行此操作吗?
问题2:如果我反复修改其中一个重复模板实例的汇编代码怎么办?也就是说,相同的符号,不同的功能体。智能编译器会检测到差异吗?
答案 0 :(得分:1)
粗略的Google搜索引导我们these OSX docs,其中指出:
.weak_definition
指令导致symbol_name
成为弱定义。symbol_name
只能在coalesced
部分中定义。 C ++编译器使用它来支持模板实例化。 [...]
继续定义coalesced
因此:
coalesced
部分可以包含任何指令或数据,并且可以在链接在一起的多个目标文件中定义符号的多个定义时使用。静态链接编辑器保留与其链接的第一个目标文件中的合并符号关联的数据,并静默地丢弃来自其他目标文件的数据。coalesced
部分的示例是编译器为C ++模板的隐式实例化生成代码的部分。
我不知道如果你修改了其中一个定义会发生什么(我还没有尝试过),但文档暗示链接器只是盲目地选择它首先找到的那个。