您提出了两个不同的问题:
boost 代码是否编译两次?是的,它确实。最终结果是编译时间可能会更长一些,因为编译器必须消化每个编译单元的所有头文件。
二进制大小是两倍?不,它可能不会,但这将归结为您选择的优化标志。在单元 A 中实例化的模板在概念上将与在单元 B 中实例化的具有完全相同类型参数的模板共享相同的实现代码。
它是否实际上共享相同的代码将取决于您的优化标志是否允许内联模板实现。如果您已允许内联并且编译器已选择这样做,那么您的二进制大小将随着编译器将模板实现与您的代码内联以实现您声明的优化目标而增加。
使用纯二进制库永远不可能内联,因此这是使用纯标头库时二进制大小可能会增长的原因之一。
下面是一个例子,展示了在未启用内联时 gcc 如何共享模板实现:
a.cpp
#include <vector>
void test1() {
std::vector<int> myvec;
myvec.push_back(1);
}
b.cpp
#include <vector>
void test2() {
std::vector<int> myvec;
myvec.push_back(1);
}
m.cpp
extern void test1(),test2();
main() {
test1();
test2();
}
编译
g++ -g -O0 -fno-inline -c m.cpp
g++ -g -O0 -fno-inline -c a.cpp
g++ -g -O0 -fno-inline -c b.cpp
g++ -o a.out a.o b.o m.o
objdump -S a.out |less
objdump分析
void test1() {
// [snip]
myvec.push_back(1);
// [snip]
4008a0: e8 d1 00 00 00 callq 400976 <_ZNSt6vectorIiSaIiEE9push_backERKi>
void test2() {
// [snip]
myvec.push_back(1);
// [snip]
401548: e8 29 f4 ff ff callq 400976 <_ZNSt6vectorIiSaIiEE9push_backERKi>
请注意如何使用 push_back 的相同实现(位置 400976),即使它被编译成完全独立的编译单元。