Значит ли использование STL значительно влияет на площадь?
Значит ли использование STL значительно влияет на площадь? Не могли бы вы, ребята, поделиться своим опытом в этом вопросе? Каковы наилучшие методы создания небольшой библиотеки footprint?
Ответы
Ответ 1
Нет ответа, поскольку STL - это набор шаблонов. Шаблоны по самой своей природе компилируются только при использовании. Таким образом, вы можете включить все STL, и если ни один из них фактически не используется, то след, добавленный STL, будет равен нулю. Если у вас очень маленькое приложение, которому удается использовать множество разных шаблонов с различными специализациями, размер отпечатка может быть большим.
Ответ 2
Вещь в STL, потому что это все шаблоны, она только добавляет размер, когда вы на самом деле используете. Если вы не используете метод, то этот метод не создается.
Но всегда будут затраты на вещи, которые вы используете.
Но реальный вопрос, который вы должны задать. Будет ли размер больше или меньше вашей собственной реализации? Если вы не используете STL, что вы используете? Вы можете писать свои собственные, но у вас есть своя стоимость. Это не нулевое пространство, оно не будет хорошо проверено, и вы не будете следовать установленным лучшим практикам.
Таким образом, на самом деле это не раздувает ваш код.
Поскольку для добавления эквивалентной функциональности другим методом будет добавлен такой же код, он просто не будет так хорошо проверен.
Другое сообщение указывает, что код шаблона должен быть выровнен или иметь несколько определений.
Это абсолютно WRONG.
Методы отмечены как встроенные. Но это зависит от компилятора, если метод фактически выровнен или нет. Встраивание компилятора достаточно сложное, чтобы быть только встроенным, если это поможет в оптимизации stratergy.
Если не вставлено, то копия метода будет сгенерирована в каждом модуле компиляции, который использует этот метод. Но ТРЕБОВАНИЕ для С++-компоновщика состоит в том, что он должен удалить ВСЕ, кроме ОДНОЙ копии этих методов, когда приложение связано с исполняемым файлом. Если компилятор не удалил лишние копии, ему пришлось бы генерировать ошибку компоновщика с несколькими определениями.
Это легко показать:
Ниже показано, что:
- Метод _M_insert_aux() не вставлен.
- Он помещается в оба блока компиляции.
- Только одна копия метода находится в финальном исполняемом файле.
a.cpp
#include <vector>
void a(std::vector<int>& l)
{
l.push_back(1);
l.at(0) = 2;
}
b.cpp
#include <vector>
void b(std::vector<int>& l)
{
l.push_back(1);
l.at(0) = 2;
}
main.cpp
#include <vector>
void a(std::vector<int>&);
void b(std::vector<int>&);
int main()
{
std::vector<int> x;
a(x);
b(x);
}
Проверка
>g++ -c a.cpp
>g++ -c b.cpp
>nm a.o
<removed other stuff>
000000a0 S __ZNSt6vectorIiSaIiEE13_M_insert_auxEN9__gnu_cxx17__normal_iteratorIPiS1_EERKi
<removed other stuff>
>nm b.o
<removed other stuff>
000000a0 S __ZNSt6vectorIiSaIiEE13_M_insert_auxEN9__gnu_cxx17__normal_iteratorIPiS1_EERKi
<removed other stuff>
>c++filt __ZNSt6vectorIiSaIiEE13_M_insert_auxEN9__gnu_cxx17__normal_iteratorIPiS1_EERKi
std::vector<int, std::allocator<int> >::_M_insert_aux(__gnu_cxx::__normal_iterator<int*, std::vector<int, std::allocator<int> > >, int const&)
>g++ a.o b.o main.cpp
nm a.out | grep __ZNSt6vectorIiSaIiEE13_M_insert_auxEN9__gnu_cxx17__normal_iteratorIPiS1_EERKi
00001700 T __ZNSt6vectorIiSaIiEE13_M_insert_auxEN9__gnu_cxx17__normal_iteratorIPiS1_EERKi
Ответ 3
Использование STL увеличит ваш двоичный размер по двум основным причинам:
Встраивание
По умолчанию компилятор обрабатывает код шаблона как встроенный. Поэтому, если вы используете std::list<int>
в нескольких разных единицах компиляции, а компилятор строит этот код, каждый из них будет иметь свои собственные локальные встроенные определения функций std::list<int>
(что, вероятно, не имеет большого значения, поскольку компилятор будет только встроенные очень маленькие определения по умолчанию).
Обратите внимание, что (как указывает Мартин в другом месте) многократно определенные символы удаляются всеми современными С++-линкерами на больших платформах, как описано в GCC документация. Таким образом, если компилятор оставляет код шаблона вне линии, компоновщик удаляет дубликаты.
Специализация
Из-за самой природы шаблонов С++ std::list<int>
потенциально произвольно отличается от std::list<double>
. Фактически, стандартный мандат, который std::vector<bool>
определяется как бит-вектор, поэтому большинство операций там полностью отличается от значения по умолчанию std::vector<T>
.
С этим может справиться только сопровождающий библиотеки. Одно из решений заключается в том, чтобы использовать базовые функции и "не подвергать шаблону". Превратите его в структуру данных в стиле C с помощью void*
везде. Затем интерфейс шаблона, который видят разработчики ниже по потоку, представляет собой тонкую оболочку. Сокращение количества дублированного кода, поскольку все специализированные шаблоны имеют общую основу.
Ответ 4
Я предполагаю, что вы имеете в виду время выполнения память, и, таким образом, STL контейнеры.
Контейнеры STL эффективны для контейнеров общего назначения. Если вы решаете между написанием собственного дважды связанного списка или использованием std:: list, пожалуйста... используйте STL. Если вы планируете писать очень специфичные для домена, бит-упакованные контейнеры для каждой из ваших конкретных потребностей, сначала используйте STL, а затем выберите свои битвы, как только ваш код будет работать правильно.
Некоторые хорошие практики:
- Если ваша библиотека будет раскрывать эти контейнеры с помощью API, вам может потребоваться выбрать способ размещения вашего STL-кода в заголовках библиотеки или не использовать STL. Проблема в том, что мой компилятор не должен реализовывать STL так же, как и ваш.
- Читайте, как и когда STL
контейнеры выделяют память. когда
вы можете визуализировать, как развивается deque
и сжимается по сравнению с вектором,
вы будете лучше подготовлены к выбору того, что использовать.
- Если вам нужно управлять каждым байт, подумайте о создании пользовательских распределителей. Это редко необходимо за пределами встроенных систем.
Ответ 5
В то время как он не адресует шаблоны STL, в документации для GCC имеется короткий раздел о минимизации размытия кода при использовании шаблонов шаблонов.
Ссылка есть
http://gcc.gnu.org/onlinedocs/gcc-4.3.2/gcc/Template-Instantiation.html#Template-Instantiation
Ответ 6
Игнорируя обсуждение STL на данный момент, существует одна неочевидная важная практика для создания статической библиотеки с низким пространством. Разделите свою библиотеку на столько разрозненных единиц компиляции, сколько сможете. Например, если вы посмотрите libpthread.a
, вы увидите, что каждая отдельная функция имеет свой собственный блок компиляции. Многие линкеры будут выкидывать мертвый код, основанный на целых единицах компиляции, но не более мелкозернистый. Если я использую только несколько функций из библиотеки pthreads, мой компоновщик будет использовать только эти определения и ничего больше. Если, с другой стороны, вся библиотека была скомпилирована в один объектный файл, мой компоновщик должен был бы привести всю библиотеку в виде единого "блока".
Это зависит от используемой инструментальной цепочки, и применяется только в том случае, если вы создаете статические библиотеки. Но я видел, что это делает очень измеримую разницу для больших библиотек, построенных не оптимально.
Ответ 7
Специализации STL, основанные на указателях, могут использовать одну и ту же реализацию. Это происходит потому, что (void *) имеет тот же размер, что и (int *) или (foo *). Итак, пока:
вектор & языки; INT & звонил; и vector & lang; foo & rang; являются различными реализациями.
vector & lang; int * & rang; и vector & lang; foo * & rang; могут участвовать в одной и той же реализации. Многие реализации STL делают это для экономии памяти.
Если весь шаблон определен в заголовке, поэтому он полностью определен, компиляторы, такие как g++, автоматически создадут копию в каждом модуле компиляции с использованием класса. Как говорили другие, компоновщик удалит несколько определений.
Они также автоматически встраивают методы в определение класса для более высоких уровней оптимизации. Но это можно контролировать с помощью параметров компилятора.
Ответ 8
Во встроенном проекте с ограничением на 64 КБ, который я когда-то делал, я даже не мог связать стандартные библиотеки C. Так что это зависит от того, что вам нужно делать