例如,考虑以下代码:
// f.h
template <typename T>
int f(T x) {
return x+1;
}
如果我们同时在
foo.cpp
和bar.cpp
中实例化它://foo.cpp instantiation:
int i = f(1);
和
//bar.cpp instantiation:
int j = f(2);
最终程序将仅使用一个代码副本吗?是这样的,当
bar.cpp
隐藏时,仅提供了目标文件bar.o
吗?我认为,由于每个cpp文件都是独立编译的,因此
foo.o
和bar.o
都必须包含f(int)
。链接器应该看到相同的重复签名,并且只能使用一个副本。我对吗? 最佳答案
是的,链接器通常会将重复的相同模板实例折叠掉。这样做非常需要避免涉及模板时二进制大小的爆炸,并保持一些标准的要求不变性,例如功能指针的等效性。这种行为有时被称为折叠。
除此之外,some linkers甚至会折叠所有碰巧内容相同的符号(即,编译相同的代码),即使它们并非源自相同的定义。有时将其称为按值折叠,但除非仔细进行,否则可能会破坏标准的含义(即因为指向不同函数的函数指针现在比较相等)。