Если у меня есть шаблон C ++, у меня есть два варианта (без экспорт ключевое слово), чтобы связать их:
Модель включения с встраиванием — т.е. включает определения вместе с объявлениями в файле .h. Это объединяет все функции и создает большой блок (хотя это лениво)
Модель включения без встраивания — то есть что-то вроде включения этого файла .h:
код:
// templateinstantiations.cpp
#include "array.cpp"template class array <int, 50>; // explicit instantiation
каждый раз, когда я хочу использовать шаблон и быть внимательным к явной реализации каждого типа, который мне нужен (это может быть скучно и сложно поддерживать)
У меня такой вопрос: я знаю, что чрезмерно встроенные функции могут вызвать перегрузку памяти и потерю производительности … кроме того, кажется, что в обоих вышеупомянутых случаях время компиляции огромно … каков компромисс между первым и вторым подходом? Есть ли критерий для выбора первого, а не второго, или мне просто нужно опробовать их и «рассчитать»?
Я думаю, этот вопрос не о шаблонах, а о вставке. В целях производительности во время выполнения компилятор, вероятно, делает правильный выбор в большинстве случаев: если он видит, что функция слишком велика, чтобы извлечь выгоду из встраивания, он, вероятно, сгенерирует не встроенную версию любой встроенной функции, независимо функции, являющейся шаблоном или нет. Каждый модуль перевода создаст свою собственную версию функции, и компоновщик выберет одну для использования (и, мы надеемся, выбрасываем другие неиспользованные копии, но зависит ли это от этого, зависит от компоновщика и формата объектного файла).
Взаимодействие с шаблонами проявляется при рассмотрении различных взаимодействий между кодом шаблона и вызываемыми им функциями, которые могут быть самими шаблонами. Когда вынуждаете код не вставлять строку, компилятор не имеет возможности избежать накладных расходов при вызове функции. Часто абстракции, используемые шаблонами, являются очень простыми функциями, например, «увеличить итератор» и «разыменовать итератор», отображая на базовые операции указателя, создание вызова функции может быть довольно дорогим из-за накладных расходов на вызов функции и потерянной возможности для оптимизации , Тем не менее, компилятор может видеть это и во многих случаях делать правильный выбор.
Тем не менее, я большой поклонник создания явных экземпляров для определенных шаблонов. Например, удаление определенных частей библиотеки IOStreams из заголовков и явное создание экземпляра в библиотеке оказывает огромное влияние на время компиляции, особенно когда включена оптимизация: вызов простой функции вывода для целого числа приводит к созданию множества шаблонов , Размещение этого кода в его собственном файле и компиляция с соответствующими параметрами оптимизации, вероятно, не окажет большого влияния на производительность, но окажет значительное влияние на время компиляции. Однако это может оказать косвенное влияние на производительность: вы можете позволить себе больше итераций для тестирования производительности кода с использованием библиотеки.
Даже когда вы явно объявляете функцию как inline
нет никаких гарантий, что C ++ сделает это inline
так как вы думаете, что реализация шаблона все в заголовке заставит inline
реализация и вызывает у вас некоторые проблемы?
Почти во всех случаях вам не нужен второй случай, хотя вы можете сделать это, но это не нужно, чтобы избежать inline
проблемы