В качестве расширений типа:
public static class TypeExtensions
{
public static IEnumerable<FieldInfo> GetConstants(this Type type)
{
var fieldInfos = type.GetFields(BindingFlags.Public | BindingFlags.Static | BindingFlags.FlattenHierarchy);
return fieldInfos.Where(fi => fi.IsLiteral && !fi.IsInitOnly);
}
public static IEnumerable<T> GetConstantsValues<T>(this Type type) where T : class
{
var fieldInfos = GetConstants(type);
return fieldInfos.Select(fi => fi.GetRawConstantValue() as T);
}
}
Вещь о STL, потому что это - все шаблоны это только, добавляет к размеру, когда Вы на самом деле используете. Если Вы не используете метод затем, что метод не инстанцируют.
, Но всегда будет стоимость для вещей, которые Вы используете.
, Но реальный вопрос необходимо спросить. Размер собирается быть больше или меньшим, чем yourt собственная реализация? Если Вы не используете STL, что Вы используете? Можно вручить записи собственное, но это имеет ее собственную стоимость. Это не нулевое пространство, это не будет хорошо протестировано, и Вы не будете применять установленные лучшие методы.
, Таким образом, в действительности не это не чрезмерно увеличивает размер Вашего кода.
, поскольку добавить, эквивалентная функциональность некоторым другим методом добавит такой же код, это просто не будет также протестировано.
Другое сообщение указывает, что код шаблона должен быть встроен или иметь повторные определения.
Это абсолютно НЕПРАВИЛЬНО .
методы отмечены как встроенные. Но это до компилятора, если метод на самом деле встраивается или нет. Встраивание компилятора достаточно сложно, чтобы только встроить, если это поможет в оптимизации stratergy быть используемым.
, Если не встроенный затем копия метода будет сгенерирована в каждой единице компиляции, которая использует метод. Но ТРЕБОВАНИЕ для компоновщика C++ - то, что это должно удалить ВСЕ кроме ОДНОЙ копии этих методов, когда приложение связано в исполняемый файл. Если бы компилятор не удалил дополнительные копии, то он должен был бы генерировать ошибку компоновщика повторного определения.
Это легко показать:
следующее иллюстрирует что:
#include <vector>
void a(std::vector<int>& l)
{
l.push_back(1);
l.at(0) = 2;
}
#include <vector>
void b(std::vector<int>& l)
{
l.push_back(1);
l.at(0) = 2;
}
#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
Нет никакого ответа, так как STL является рядом шаблонов. Шаблоны, по самой своей природе, только компилируются в при использовании. Таким образом, можно включать весь STL и если ни один из него не будет на самом деле использоваться, то место, добавленное STL, будет нулем. Если у Вас есть очень небольшое приложение, которому удается использовать много различных шаблонов с различными специализациями, место может быть большим.
Я предполагаю, что Вы имеете в виду время выполнения память место и таким образом STL контейнеры .
контейнеры STL эффективны для того, что они-... контейнеры общего назначения. Если Вы решаете между записью Вашего собственного двунаправленного связанного списка или использованием станд.:: список... используйте STL. Если Вы считаете запись очень проблемно-ориентированными, побитно упакованными контейнерами для каждой из Ваших определенных потребностей, используйте STL сначала и затем выберите Ваши сражения, после того как весь Ваш код работает правильно.
Некоторые хорошие методы:
Игнорирование обсуждения STL в настоящий момент, существует одна неочевидная важная практика для создания низкого места пространства статическая библиотека. Разделите свою библиотеку в столько разрозненных единиц компиляции, сколько Вы можете. Например, если Вы посмотрите libpthread.a
, то Вы будете видеть, что каждая функция имеет свою собственную единицу компиляции. Многие компоновщики выведут мертвый код на основе целых единиц компиляции, но не больше мелкомодульные, чем это. Если я только буду использовать несколько функций из pthreads библиотеки, то мой компоновщик введет только те определения и ничто иное. Если бы с другой стороны, вся библиотека была скомпилирована в файл отдельного объекта, то мой компоновщик должен был бы ввести всю библиотеку как единственную "единицу".
Это зависит от набора инструментальных средств, который Вы используете, и он только применяется при создании статических библиотек. Но я видел, что он имеет очень измеримое значение для крупных библиотек, созданных субоптимальным образом.
В то время как это не обращается к шаблонам STL, документация для GCC имеет короткий раздел по уменьшению чрезмерного увеличения размера кода при использовании шаблонных шаблонов.
ссылка http://gcc.gnu.org/onlinedocs/gcc-4.3.2/gcc/Template-Instantiation.html#Template-Instantiation
Специализации STL на основе указателей могут совместно использовать ту же реализацию. Это, с тех пор (пусто *) имеет тот же размер как (интервал *) или (нечто *). Итак, в то время как:
vector〈 int〉 и vector〈 foo〉 различные реализации.
vector〈 интервал *〉 и vector〈 нечто *〉 может совместно использовать большую часть той же реализации. Много реализаций STL делают это для сохранения объема потребляемой памяти.
, Если весь шаблон определяется в заголовке, таким образом, он полностью определяется, компиляторы как g ++ автоматически создадут копию в каждой единице компиляции с помощью класса. Как другие сказали, компоновщик удалит повторные определения.
Они также автоматически встроят методы в определении класса для более высоких уровней оптимизации. Но этим можно управлять с параметрами компилятора.
Используя STL увеличит Ваш двоичный размер для двух основных причин:
По умолчанию, компилятор рассматривает код шаблона как встроенный. Поэтому, если Вы будете использовать std::list<int>
в нескольких различных единицах компиляции, , и компилятор встраивает тот код , то у них каждый будут свои собственные локальные встроенные определения std::list<int>
функции (который, вероятно, не является грандиозным предприятием, так как компилятор только встроит очень маленькие определения по умолчанию).
Примечание, которые (поскольку Martin указывает в другом месте) умножаются - определенные символы разделяются всеми современными компоновщиками C++ на больших платформах, как описано в документация GCC . Таким образом, если компилятор оставит код шаблона исключительным, то компоновщик удалит дубликаты.
из-за самой природы шаблонов C++, std::list<int>
потенциально произвольно отличается, чем std::list<double>
. На самом деле стандартные мандаты, который std::vector<bool>
определяется как битовый вектор, так большинство операций, там полностью отличающиеся, чем значение по умолчанию std::vector<T>
.
Только специалист по обслуживанию библиотеки может иметь дело с этим. Одно решение состоит в том, чтобы взять базовую функциональность и "un-templatize" это. Превратите его в структуру данных C-стиля с void*
везде. Затем шаблонный интерфейс, который видят нисходящие разработчики, является тонкой оберткой. Уменьшение объема дублированного кода, потому что шаблонные специализации вся доля общее основание.
На встроенном проекте с пределом 64 КБ я однажды сделал, я не мог даже связать стандартные библиотеки для C. Таким образом, это зависит от того, что необходимо сделать
== true
никогда неявны сbool?
– Heliac 4 June 2014 в 17:59