Когда я включаю заголовок hpp библиотеки boost в два блока перевода, компилируется ли код 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), даже если он был скомпилирован в отдельные блоки компиляции.
Есть несколько заголовочных файлов boost, которые особенно велики (я смотрю на вас boost / lexical_cast.hpp), что приведет к увеличению размера двоичного файла. Тем не менее, компиляторы предлагают несколько вариантов, чтобы помочь:
MSVC имеет опцию / LTCG (генерация кода времени соединения)
GCC имеет -flto (я полагаю, включен с -O3)
Эти параметры обычно позволяют компоновщику отбрасывать неиспользуемые компоненты и уменьшать дублирование в модуле компиляции.