Кілька причин
Файли заголовків
Кожна одиниця компіляції вимагає завантаження (1) та (2) сотень і навіть тисяч заголовків. Кожен з них, як правило, повинен бути перекомпільований для кожної одиниці компіляції, оскільки препроцесор гарантує, що результат компіляції заголовка може відрізнятися між кожним блоком компіляції. (Макрос може бути визначений в одній одиниці компіляції, яка змінює вміст заголовка).
Це, ймовірно , основною причиною, так як він вимагає величезної кількості коду, скомпільовані для кожної одиниці компіляції, і , крім того, кожен заголовок повинен бути складений кілька разів (один раз для кожної одиниці компіляції , яка включає його).
Зв’язування
Після компіляції всі об’єктні файли повинні бути пов'язані між собою. Це в основному монолітний процес, який не дуже добре можна паралелізувати і повинен обробляти весь ваш проект.
Розбір
Синтаксис надзвичайно складний для розбору, сильно залежить від контексту, і його дуже важко роз'єднати. Це займає багато часу.
Шаблони
У C # List<T>
- єдиний тип, який складається, незалежно від того, скільки наявних у вашій програмі списків. У C ++ vector<int>
- це абсолютно окремий тип vector<float>
, і кожен з них повинен бути складений окремо.
Додайте до цього, що шаблони складають повну "підмову", яку повинен інтерпретувати компілятор, і це може стати смішно складним. Навіть порівняно простий код метапрограмування шаблону може визначати рекурсивні шаблони, які створюють десятки і десятки шаблонів шаблонів. Також шаблони можуть спричинити надзвичайно складні типи з смішно довгими назвами, що додасть багато додаткової роботи для лінкера. (Слід порівняти багато імен символів, і якщо ці імена можуть перерости у багато тисяч символів, це може стати досить дорогим).
І звичайно, вони посилюють проблеми з файлами заголовків, оскільки шаблони, як правило, мають бути визначені в заголовках, а це означає, що для кожного компіляційного блоку потрібно проаналізувати набагато більше коду. У звичайному коді С заголовок, як правило, містить лише прямі декларації, але фактично дуже мало коду. У C ++ не рідкість майже весь код розташований у файлах заголовків.
Оптимізація
C ++ дозволяє зробити дуже драматичні оптимізації. C # або Java не дозволяють повністю видалити класи (вони повинні бути там для цілей рефлексії), але навіть проста метапрограма шаблону C ++ може легко генерувати десятки чи сотні класів, всі вони окреслені та усунені в процесі оптимізації фаза.
Крім того, компілятор повинен повністю оптимізувати програму C ++. Програма AC # може розраховувати на компілятор JIT для виконання додаткових оптимізацій під час завантаження, C ++ не отримує жодних таких "друге шансів". Те, що створює компілятор, настільки ж оптимізовано, як і збирається отримати.
Машина
C ++ компілюється до машинного коду, який може бути дещо складнішим, ніж використання байт-коду Java або .NET (особливо у випадку x86). (Про це йдеться лише у повноті лише тому, що це було зазначено в коментарях тощо). На практиці цей крок навряд чи займе більше ніж незначну частину загального часу складання).
Висновок
Більшість цих факторів поділяється кодом С, який насправді збирається досить ефективно. Крок розбору набагато складніше в C ++ і може зайняти значно більше часу, але головний правопорушник, мабуть, шаблони. Вони корисні та роблять C ++ набагато більш потужною мовою, але вони також приймають свою плату за швидкістю компіляції.