как работают шаблоны, всегда ли они встроены? - PullRequest
6 голосов
/ 25 марта 2011

Я могу понять, как это работает, если они встроены. Но если они не, как это работает? все ли объектные файлы получают собственную копию, например, шаблона функции?

Ответы [ 6 ]

4 голосов
/ 25 марта 2011

Шаблоны будут встроены в стандартном значении inline, что больше относится к правилу единого определения, чем к фактическому встраиванию кода.То есть компоновщик не будет жаловаться, если функции шаблона определены более чем в одной единице перевода, он просто выберет одну (будьте осторожны: случайная, текущие компиляторы не будут жаловаться, если вы предоставите разные определения шаблона в разных единицах перевода!) и оставьте это в окончательном двоичном файле.

Теперь, как и со всеми другими inline функциями, компилятор может решить, что это хорошая идея - на самом деле избегать вызова функции и встроить функцию в местовызов, или он может определить, что это не очень хорошая идея (большая функция, некоторые компиляторы не включают встроенные функции с вложенными циклами ... по любой причине), и тогда он не будет выполнять фактическую вставку кода.

2 голосов
/ 25 марта 2011

Это зависит. Некоторые из наиболее популярных реализаций делают создать копию кода реализации в каждом объектном файле который запускает инстанцирование и рассчитывает на компоновщик выбросить все, кроме одного. Другие компиляторы используют какие-то хранилище, где хранятся экземпляры; если экземпляр уже присутствует, компилятор не беспокоит восстанавливать его. Это решение значительно быстрее и использует меньше диска, чем в первом решении, но это также намного сложнее быть правым. (Компилятор должен сгенерировать новый экземпляр не только если один не присутствует, но если какой-либо из файлов инстанцирование зависит от того, что изменилось.)

2 голосов
/ 25 марта 2011

Зависит от компилятора, но каждый, на кого я смотрел, создает функцию, которая затем вызывается с использованием параметров замещенного шаблона для генерации кода для каждого из вариантов.

в качестве (очень) простого примера:

template <typename T> T Max(T a, T b)
{
    return a > b ? a : b;
}

, когда он вызывается как Max<int> и Max<float> и не встроен, компилятор генерирует (однако они оформлены специальным образом, чтобы избежать других проблем):

int Max(int a, int b)
{
    return a > b ? a : b;
}

float Max(float a, float b)
{
    return a > b ? a : b;
}

Затем он застревает в начале объекта, а затем на него ссылаются, затем то же самое делается для некоторых строк (в MSVC)

1 голос
/ 25 марта 2011

это зависит от реализации.

Но, как правило, да, каждый объектный файл получает копию каждой расширенной функции, которую они используют. И тогда компоновщик замечает это во время компоновки и гарантирует, что только одна копия функции помещается в окончательный исполняемый файл

0 голосов
/ 26 марта 2011

Шаблоны - это полноценный язык для себя.Они завершены по Тьюрингу, но «программа» запускается во время компиляции.Это фабрики кода, которые заменяют тип объекта во время компиляции и собирают классы, функции и т. Д. Во время компиляции.Таким образом, вы можете думать о нем как о безопасном для типов, совместимом с C ++ языке массивной предварительной обработки.Результатом выполнения является чистый код C ++, который затем может обрабатываться компилятором так же, как и все остальное.

Компиляторы обычно игнорируют inline, так как очень немногие программисты могут знать, когда это лучше, и те, ктоне оставили сборку.

0 голосов
/ 25 марта 2011

Шаблоны действительно очень продвинутые MACROS (#define)

параметры заменяются во время компиляции на переданные значенияДействительно отличная концепция, а также реализована очень хорошо.

...