Nhiều lý do
Tập tin tiêu đề
Mỗi đơn vị biên dịch đơn lẻ yêu cầu hàng trăm hoặc thậm chí hàng ngàn tiêu đề được (1) được tải và (2) được biên dịch. Mỗi một trong số chúng thường phải được biên dịch lại cho mọi đơn vị biên dịch, bởi vì bộ xử lý trước đảm bảo rằng kết quả biên dịch một tiêu đề có thể khác nhau giữa mỗi đơn vị biên dịch. (Một macro có thể được xác định trong một đơn vị biên dịch làm thay đổi nội dung của tiêu đề).
Đây có lẽ là những nguyên nhân chủ yếu, vì nó đòi hỏi một lượng lớn các mã được biên dịch cho mỗi đơn vị biên soạn, và thêm vào đó, tất cả các tiêu đề phải được biên soạn nhiều lần (một lần cho mỗi đơn vị biên soạn bao gồm nó).
Liên kết
Sau khi biên dịch, tất cả các tệp đối tượng phải được liên kết với nhau. Về cơ bản, đây là một quá trình nguyên khối không thể song song và phải xử lý toàn bộ dự án của bạn.
Phân tích cú pháp
Cú pháp cực kỳ phức tạp để phân tích cú pháp, phụ thuộc rất nhiều vào ngữ cảnh và rất khó để định hướng. Điều này mất rất nhiều thời gian.
Mẫu
Trong C #, List<T>
là loại duy nhất được biên dịch, bất kể bạn có bao nhiêu lần hiển thị Danh sách trong chương trình của mình. Trong C ++, vector<int>
là một loại hoàn toàn riêng biệt vector<float>
và mỗi loại sẽ phải được biên dịch riêng.
Thêm vào đó là các mẫu tạo nên một "ngôn ngữ con" hoàn chỉnh Turing đầy đủ mà trình biên dịch phải diễn giải, và điều này có thể trở nên phức tạp một cách lố bịch. Ngay cả mã siêu lập trình mẫu tương đối đơn giản cũng có thể xác định các mẫu đệ quy tạo ra hàng chục và hàng chục mẫu tức thời. Các mẫu cũng có thể dẫn đến các loại cực kỳ phức tạp, với các tên dài kỳ cục, thêm rất nhiều công việc phụ vào trình liên kết. (Nó phải so sánh rất nhiều tên biểu tượng, và nếu những tên này có thể phát triển thành nhiều nghìn ký tự, điều đó có thể trở nên khá đắt đỏ).
Và tất nhiên, chúng làm trầm trọng thêm các vấn đề với các tệp tiêu đề, bởi vì các mẫu thường phải được xác định trong các tiêu đề, điều đó có nghĩa là nhiều mã hơn phải được phân tích và biên dịch cho mọi đơn vị biên dịch. Trong mã C đơn giản, một tiêu đề thường chỉ chứa các khai báo chuyển tiếp, nhưng rất ít mã thực tế. Trong C ++, hầu như không có gì lạ khi hầu hết tất cả các mã nằm trong các tệp tiêu đề.
Tối ưu hóa
C ++ cho phép một số tối ưu hóa rất ấn tượng. C # hoặc Java không cho phép các lớp bị loại bỏ hoàn toàn (chúng phải ở đó cho mục đích phản chiếu), nhưng ngay cả một siêu dữ liệu mẫu C ++ đơn giản cũng có thể dễ dàng tạo ra hàng chục hoặc hàng trăm lớp, tất cả chúng được nội tuyến và loại bỏ một lần nữa trong tối ưu hóa giai đoạn.
Hơn nữa, một chương trình C ++ phải được trình biên dịch tối ưu hóa hoàn toàn. Chương trình AC # có thể dựa vào trình biên dịch JIT để thực hiện tối ưu hóa bổ sung tại thời điểm tải, C ++ không nhận được bất kỳ "cơ hội thứ hai" nào như vậy. Những gì trình biên dịch tạo ra được tối ưu hóa như nó sẽ nhận được.
Máy móc
C ++ được biên dịch thành mã máy có thể phức tạp hơn một chút so với sử dụng Java hoặc .NET (đặc biệt là trong trường hợp x86). (Điều này được đề cập không đầy đủ chỉ vì nó đã được đề cập trong các bình luận và như vậy. Trong thực tế, bước này khó có thể mất nhiều hơn một phần rất nhỏ trong tổng thời gian biên dịch).
Phần kết luận
Hầu hết các yếu tố này được chia sẻ bởi mã C, thực sự biên dịch khá hiệu quả. Bước phân tích cú pháp phức tạp hơn rất nhiều trong C ++ và có thể chiếm nhiều thời gian hơn đáng kể, nhưng người vi phạm chính có lẽ là các mẫu. Chúng rất hữu ích và làm cho C ++ trở thành một ngôn ngữ mạnh mẽ hơn nhiều, nhưng chúng cũng gây ảnh hưởng về tốc độ biên dịch.