(类似提升)仅标头库如何影响编译大小

How does (boost like) header only libraries influence compilation size?

本文关键字:何影响 影响 编译      更新时间:2023-10-16

当我在两个翻译单元中包含提升库 hpp 标头时,提升代码是否编译两次(与传统的预编译库相比,二进制大小翻倍?

你问了两个不同的问题:

提升代码编译两次吗?是的,确实如此。实际效果是编译时间可能会更长一些,因为编译器必须消化每个编译单元的所有标头。

二进制大小是双倍?不,它可能没有,但这将归结为您选择的优化标志。在单元 A 中实例化的模板在名义上将与单元 B 中实例化的模板共享相同的实现代码,具有完全相同的类型参数。

它是否实际共享相同的代码取决于您的优化标志是否允许内联模板实现。如果您允许内联并且编译器已选择这样做,则随着编译器将模板实现与您的代码内联以实现您声明的优化目标,您的二进制大小将增加。

使用仅

二进制库永远无法内联,因此这是使用仅标头库时二进制大小可能会增长的原因之一。

以下示例显示了 gcc 在未启用内联时如何共享模板实现:

答.cpp

#include <vector>
void test1() {
  std::vector<int> myvec;
  myvec.push_back(1);
}

乙.cpp

#include <vector>
void test2() {
  std::vector<int> myvec;
  myvec.push_back(1);
}

米.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(,即使它被编译为完全独立的编译单元。

有一些 boost

头文件特别大(我在看你 boost/lexical_cast.hpp(,这将导致二进制文件更大。但是,编译器提供了一些选项来提供帮助:

MSVC 有一个选项/LTCG(链接时代码生成(

GCC 有 -flto(我相信是用 -O3 启用的(

这些选项通常允许链接器丢弃未使用的组件,并减少整个编译单元中的重复。