Есть несколько вещей, которые делают компилятор C ++ медленнее, чем в Java / C #. Грамматика намного сложнее, универсальная поддержка программирования гораздо мощнее в C ++, но в то же время она дороже компилируется. Включение файлов работает иначе, чем импорт модулей.
Включение заголовочных файлов
Во-первых, всякий раз, когда вы включаете файл в C ++, содержимое файла (обычно .h) внедряется в текущий модуль компиляции (включая элементы защиты, избегающие повторного введения одного и того же заголовка дважды), и это транзитивно. То есть, если вы включите заголовок a.h, который по очереди включает b.h, ваш модуль компиляции будет включать весь код в a.h и весь код в b.h.
Java (или C #, я буду говорить о Java, но они похожи в этом) не имеют включаемых файлов, они зависят от двоичных файлов при компиляции используемых классов. Это означает, что всякий раз, когда вы компилируете a.java, который использует объект B, определенный в b.java, он просто проверяет двоичный класс b.class, ему не нужно углубляться, чтобы проверить зависимости B, поэтому он может сократить процесс раньше (только с одним уровнем проверки).
В то же время, включение файлов включает только определения языка, и для его обработки требуется время. Когда компилятор Java / C # читает двоичный файл, он имеет ту же информацию, но уже обработанную на этапе компиляции, который его сгенерировал.
Итак, в конце концов, в C / C ++ включено больше файлов, и в то же время обработка этих включений обходится дороже, чем обработка двоичных модулей.
Шаблоны
Шаблоны по-своему особенные. Их можно предварительно скомпилировать, но обычно это не так (по ряду причин). Это означает, что во всех модулях компиляции, которые используют std :: vector, весь набор используемых векторных методов (неиспользуемые методы шаблона не компилируются) обрабатывается и двоичный код генерируется компилятором. На более позднем этапе, во время компоновки, избыточные определения того же метода будут отброшены, но во время компиляции они должны быть обработаны.
Поддержка в Java для обобщений более ограничена во многих отношениях. В конце, например, есть только один двоичный файл класса Vector, и всякий раз, когда компилятор видит Vector в java, он генерирует код проверки типа перед делегированием в реальную реализацию Vector (которая хранит простой объект), и это не является универсальным. Компилятор предоставляет гарантии типов, но не компилирует Vector для каждого типа.
В C # это опять-таки другое. Поддержка универсальных шаблонов в C # более сложна, чем в Java, и в конце универсальные классы отличаются от простых классов, но в любом случае они компилируются только один раз, поскольку двоичный формат содержит всю необходимую информацию.