Tại sao quá trình biên dịch C ++ lại mất nhiều thời gian như vậy?


540

Việc biên dịch tệp C ++ mất một thời gian rất dài khi so sánh với C # và Java. Sẽ mất nhiều thời gian hơn để biên dịch tệp C ++ so với chạy tập lệnh Python có kích thước bình thường. Tôi hiện đang sử dụng VC ++ nhưng nó giống với bất kỳ trình biên dịch nào. Tại sao lại thế này?

Hai lý do tôi có thể nghĩ đến là tải các tệp tiêu đề và chạy bộ tiền xử lý, nhưng điều đó dường như không giải thích được tại sao nó lại mất nhiều thời gian như vậy.


58
VC ++ hỗ trợ các tiêu đề được biên dịch trước. Sử dụng chúng sẽ giúp. Rất nhiều.
Brian

1
Có trong trường hợp của tôi (chủ yếu là C với một vài lớp - không có mẫu) các tiêu đề được biên dịch trước tăng tốc khoảng 10 lần
Lothar

@Brian Tôi sẽ không bao giờ sử dụng một đầu được biên dịch sẵn trong thư viện
Cole Johnson

13
It takes significantly longer to compile a C++ file- bạn có nghĩa là 2 giây so với 1 giây? Chắc chắn đó là dài gấp đôi, nhưng hầu như không đáng kể. Hay bạn có nghĩa là 10 phút so với 5 giây? Hãy định lượng.
Nick Gammon

2
Tôi đặt cược vào các mô-đun; Tôi không hy vọng các dự án C ++ sẽ được xây dựng nhanh hơn so với các ngôn ngữ lập trình khác chỉ làm với các mô-đun, nhưng nó có thể thực sự gần gũi với hầu hết các dự án với một số quản lý. Tôi hy vọng sẽ thấy một trình quản lý gói tốt với tích hợp nhân tạo sau các mô-đun
Abdurrahim

Câu trả lời:


800

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.


38
Về điểm 3: Quá trình biên dịch C nhanh hơn đáng kể so với C ++. Đó chắc chắn là lối vào gây ra sự chậm chạp và không tạo ra mã.
Tom

72
Về các mẫu: không chỉ vectơ <int> phải được biên dịch tách biệt với vectơ <double>, mà vectơ <int> được biên dịch lại trong mỗi đơn vị biên dịch sử dụng nó. Các định nghĩa dư thừa được loại bỏ bởi các trình liên kết.
David Rodríguez - dribeas

15
dribeas: Đúng, nhưng điều đó không cụ thể cho các mẫu. Các hàm nội tuyến hoặc bất kỳ thứ gì khác được xác định trong các tiêu đề sẽ được biên dịch lại ở mọi nơi. Nhưng vâng, điều đó đặc biệt đau đớn với các mẫu. :)
jalf

15
@configurator: Visual Studio và gcc đều cho phép các tiêu đề được biên dịch trước, có thể mang lại một số tốc độ tăng tốc nghiêm trọng cho quá trình biên dịch.
small_duck

5
Không chắc chắn nếu tối ưu hóa là vấn đề, vì các bản dựng DEBUG của chúng tôi thực sự chậm hơn các bản dựng chế độ phát hành. Thế hệ pdb cũng là một thủ phạm.
gast128

40

Sự chậm lại không nhất thiết giống với bất kỳ trình biên dịch nào.

Tôi chưa sử dụng Delphi hoặc Kylix nhưng vào thời MS-DOS, một chương trình Turbo Pascal sẽ biên dịch gần như ngay lập tức, trong khi chương trình Turbo C ++ tương đương sẽ chỉ thu thập dữ liệu.

Hai điểm khác biệt chính là hệ thống mô-đun rất mạnh và cú pháp cho phép biên dịch một lần.

Chắc chắn rằng tốc độ biên dịch không phải là ưu tiên hàng đầu của các nhà phát triển trình biên dịch C ++, nhưng cũng có một số biến chứng cố hữu trong cú pháp C / C ++ khiến việc xử lý khó khăn hơn. (Tôi không phải là chuyên gia về C, nhưng Walter Bright là và sau khi xây dựng nhiều trình biên dịch C / C ++ thương mại khác nhau, anh ấy đã tạo ra ngôn ngữ D. Một trong những thay đổi của anh ấy là thi hành một ngữ pháp không ngữ cảnh để làm cho ngôn ngữ dễ phân tích hơn .)

Ngoài ra, bạn sẽ nhận thấy rằng các Makefiles thường được thiết lập sao cho mọi tệp được biên dịch riêng trong C, vì vậy nếu 10 tệp nguồn đều sử dụng cùng một tệp bao gồm, tệp bao gồm được xử lý 10 lần.


38
Thật thú vị khi so sánh Pascal, vì Niklaus Wirth đã sử dụng thời gian để trình biên dịch tự biên dịch thành chuẩn để thiết kế ngôn ngữ và trình biên dịch của mình. Có một câu chuyện rằng sau khi cẩn thận viết một mô-đun để tra cứu biểu tượng nhanh, ông đã thay thế nó bằng một tìm kiếm tuyến tính đơn giản vì kích thước mã giảm làm cho trình biên dịch tự biên dịch nhanh hơn.
Dietrich Epp

1
@DietrichEpp Chủ nghĩa kinh nghiệm được đền đáp.
Tomas Zubiri

40

Phân tích cú pháp và tạo mã thực sự khá nhanh. Vấn đề thực sự là mở và đóng tập tin. Hãy nhớ rằng, ngay cả với các bộ bảo vệ, trình biên dịch vẫn mở tệp .H và đọc từng dòng (và sau đó bỏ qua nó).

Một người bạn một lần (trong khi buồn chán tại nơi làm việc), đã lấy ứng dụng của công ty mình và đặt mọi thứ - tất cả các tệp nguồn và tiêu đề - vào một tệp lớn. Thời gian biên dịch giảm từ 3 giờ xuống còn 7 phút.


14
Chà, truy cập tệp chắc chắn có tác dụng trong việc này nhưng như jalf đã nói, lý do chính cho việc này sẽ là một thứ khác, cụ thể là phân tích cú pháp lặp đi lặp lại của nhiều, rất nhiều, rất nhiều tệp tiêu đề (lồng nhau!) Hoàn toàn bỏ qua trong trường hợp của bạn.
Konrad Rudolph

9
Tại thời điểm đó, bạn của bạn cần thiết lập các tiêu đề được biên dịch sẵn, ngắt các phụ thuộc giữa các tệp tiêu đề khác nhau (cố gắng tránh một tiêu đề bao gồm một tiêu đề khác, thay vào đó là khai báo về phía trước) và nhận được một ổ cứng nhanh hơn. Điều đó sang một bên, một số liệu khá tuyệt vời.
Tom Leys

6
Nếu toàn bộ tệp tiêu đề (ngoại trừ các bình luận có thể và các dòng trống) nằm trong bộ bảo vệ tiêu đề, gcc có thể nhớ tệp và bỏ qua nếu ký hiệu chính xác được xác định.
CesarB

11
Phân tích cú pháp là một vấn đề lớn. Đối với N cặp tệp nguồn / tiêu đề có kích thước tương tự có sự phụ thuộc lẫn nhau, có O (N ^ 2) đi qua các tệp tiêu đề. Đặt tất cả văn bản vào một tệp sẽ cắt giảm phân tích cú pháp trùng lặp đó.
Tom

9
Lưu ý bên nhỏ: Bộ bảo vệ bao gồm bảo vệ chống lại nhiều phân tích cú pháp trên mỗi đơn vị biên dịch. Không chống lại nhiều phân tích tổng thể.
Marco van de Voort

16

Một lý do khác là việc sử dụng bộ xử lý trước C để định vị khai báo. Ngay cả với các bộ bảo vệ tiêu đề, .h vẫn phải được phân tích lặp đi lặp lại, mỗi khi chúng được bao gồm. Một số trình biên dịch hỗ trợ các tiêu đề được biên dịch trước có thể giúp với điều này, nhưng chúng không phải lúc nào cũng được sử dụng.

Xem thêm: C ++ Câu hỏi thường gặp


Tôi nghĩ bạn nên in đậm nhận xét về các tiêu đề được biên dịch trước để chỉ ra phần QUAN TRỌNG này trong câu trả lời của bạn.
Kevin

6
Nếu toàn bộ tệp tiêu đề (ngoại trừ các bình luận có thể và các dòng trống) nằm trong bộ bảo vệ tiêu đề, gcc có thể nhớ tệp và bỏ qua nếu ký hiệu chính xác được xác định.
CesarB

5
@CesarB: Nó vẫn phải xử lý đầy đủ một lần cho mỗi đơn vị biên dịch (tệp .cpp).
Sam Harwell

16

C ++ được biên dịch thành mã máy. Vì vậy, bạn có bộ xử lý trước, trình biên dịch, trình tối ưu hóa và cuối cùng là trình biên dịch, tất cả đều phải chạy.

Java và C # được biên dịch thành mã byte / IL và máy ảo Java / .NET Framework thực thi (hoặc biên dịch JIT thành mã máy) trước khi thực hiện.

Python là một ngôn ngữ được giải thích cũng được biên dịch thành mã byte.

Tôi chắc chắn cũng có những lý do khác cho việc này, nhưng nói chung, không phải biên dịch sang ngôn ngữ máy gốc giúp tiết kiệm thời gian.


15
Chi phí được thêm vào bởi tiền xử lý là không đáng kể. "Lý do chính" khác cho sự chậm lại là việc biên dịch được chia thành các tác vụ riêng biệt (một cho mỗi tệp đối tượng), vì vậy các tiêu đề phổ biến được xử lý lặp đi lặp lại. Đó là trường hợp xấu nhất O (N ^ 2), so với hầu hết các ngôn ngữ khác thời gian phân tích O (N).
Tom

12
Bạn có thể nói từ cùng một lập luận rằng các trình biên dịch C, Pascal, v.v ... chậm, điều này không đúng với trung bình. Nó liên quan nhiều hơn đến ngữ pháp của C ++ và trạng thái to lớn mà trình biên dịch C ++ phải duy trì.
Sebastian Mach

2
C chậm. Nó bị vấn đề phân tích cú pháp tiêu đề tương tự như là giải pháp được chấp nhận. Ví dụ: lấy một chương trình GUI windows đơn giản bao gồm windows.h trong một vài đơn vị biên dịch và đo hiệu suất biên dịch khi bạn thêm các đơn vị biên dịch (ngắn).
Marco van de Voort

14

Các vấn đề lớn nhất là:

1) Tiêu đề vô hạn reparsing. Đã được đề cập. Giảm thiểu (như #pragma một lần) thường chỉ hoạt động trên mỗi đơn vị biên dịch, không phải trên mỗi bản dựng.

2) Thực tế là chuỗi công cụ thường được phân tách thành nhiều nhị phân (tạo, tiền xử lý, trình biên dịch, trình biên dịch, lưu trữ, impdef, linker và dlltool trong các trường hợp cực đoan) mà tất cả đều phải khởi động lại và tải lại tất cả trạng thái cho mỗi lần gọi ( trình biên dịch, trình biên dịch) hoặc mỗi vài tệp (lưu trữ, liên kết và dlltool).

Xem thêm cuộc thảo luận này trên comp.compilers: http://compilers.iecc.com/comparch/article/03-11-078 đặc biệt bài này:

http://compilers.iecc.com/comparch/article/02-07-128

Lưu ý rằng John, người điều hành comp.compilers dường như đồng ý và điều này có nghĩa là cũng có thể đạt được tốc độ tương tự cho C, nếu một người tích hợp đầy đủ chuỗi công cụ và thực hiện các tiêu đề được biên dịch trước. Nhiều trình biên dịch C thương mại làm điều này ở một mức độ nào đó.

Lưu ý rằng mô hình Unix bao thanh toán mọi thứ cho một nhị phân riêng biệt là một loại mô hình trường hợp xấu nhất cho Windows (với quá trình tạo chậm của nó). Điều rất đáng chú ý khi so sánh thời gian xây dựng GCC giữa Windows và * nix, đặc biệt nếu hệ thống make / configure cũng gọi một số chương trình chỉ để lấy thông tin.


13

Xây dựng C / C ++: điều gì thực sự xảy ra và tại sao nó lại mất nhiều thời gian như vậy

Một phần tương đối lớn thời gian phát triển phần mềm không dành cho việc viết, chạy, gỡ lỗi hoặc thậm chí thiết kế mã, mà chờ nó hoàn thành biên dịch. Để làm cho mọi thứ nhanh chóng, trước tiên chúng ta phải hiểu những gì đang xảy ra khi phần mềm C / C ++ được biên dịch. Các bước đại khái như sau:

  • Cấu hình
  • Xây dựng công cụ khởi động
  • Kiểm tra phụ thuộc
  • Biên soạn
  • Liên kết

Bây giờ chúng ta sẽ xem xét từng bước chi tiết hơn tập trung vào cách chúng có thể được thực hiện nhanh hơn.

Cấu hình

Đây là bước đầu tiên khi bắt đầu xây dựng. Thông thường có nghĩa là chạy tập lệnh cấu hình hoặc CMake, Gyp, SCons hoặc một số công cụ khác. Việc này có thể mất bất cứ thứ gì từ một giây đến vài phút đối với các tập lệnh cấu hình dựa trên Autotools rất lớn.

Bước này xảy ra tương đối hiếm khi. Nó chỉ cần được chạy khi thay đổi cấu hình hoặc thay đổi cấu hình bản dựng. Thiếu thay đổi hệ thống xây dựng, không có nhiều việc phải làm để thực hiện bước này nhanh hơn.

Xây dựng công cụ khởi động

Đây là những gì xảy ra khi bạn chạy make hoặc nhấp vào biểu tượng xây dựng trên IDE (thường là bí danh để thực hiện). Công cụ xây dựng nhị phân bắt đầu và đọc các tệp cấu hình của nó cũng như cấu hình xây dựng, thường là cùng một thứ.

Tùy thuộc vào độ phức tạp và kích thước của bản dựng, quá trình này có thể mất từ ​​một phần giây đến vài giây. Tự nó sẽ không tệ đến thế. Thật không may, hầu hết các hệ thống xây dựng dựa trên tạo nên khiến cho được tạo ra hàng chục đến hàng trăm lần cho mỗi bản dựng. Thông thường điều này được gây ra bởi việc sử dụng đệ quy của make (đó là xấu).

Cần lưu ý rằng lý do Make quá chậm không phải là lỗi thực thi. Cú pháp của Makefiles có một số điểm kỳ quặc giúp thực hiện rất nhanh nhưng không thể. Vấn đề này thậm chí còn đáng chú ý hơn khi kết hợp với bước tiếp theo.

Kiểm tra phụ thuộc

Khi công cụ xây dựng đã đọc cấu hình của nó, nó phải xác định những tập tin nào đã thay đổi và những tập tin nào cần được biên dịch lại. Các tệp cấu hình chứa một biểu đồ chu kỳ có hướng mô tả các phụ thuộc của bản dựng. Biểu đồ này thường được xây dựng trong bước cấu hình. Xây dựng thời gian khởi động công cụ và trình quét phụ thuộc được chạy trên mỗi bản dựng. Thời gian chạy kết hợp của chúng xác định giới hạn dưới của chu trình chỉnh sửa-biên dịch-gỡ lỗi. Đối với các dự án nhỏ thời gian này thường là một vài giây hoặc lâu hơn. Điều này là chấp nhận được. Có những lựa chọn thay thế để thực hiện. Nhanh nhất trong số đó là Ninja, được xây dựng bởi các kỹ sư của Google cho Chromium. Nếu bạn đang sử dụng CMake hoặc Gyp để xây dựng, chỉ cần chuyển sang phần phụ trợ Ninja của họ. Bạn không phải thay đổi bất cứ điều gì trong các tệp xây dựng, chỉ cần tận hưởng tốc độ tăng. Ninja không được đóng gói trên hầu hết các bản phân phối, mặc dù,

Biên soạn

Tại thời điểm này, chúng tôi cuối cùng đã gọi trình biên dịch. Cắt một số góc, đây là các bước gần đúng được thực hiện.

  • Sáp nhập bao gồm
  • Phân tích cú pháp mã
  • Tạo / tối ưu hóa mã

Trái với niềm tin phổ biến, việc biên dịch C ++ không thực sự quá chậm. STL chậm và hầu hết các công cụ xây dựng được sử dụng để biên dịch C ++ đều chậm. Tuy nhiên, có những công cụ và cách nhanh hơn để giảm thiểu những phần chậm của ngôn ngữ.

Sử dụng chúng cần một chút mỡ khuỷu tay, nhưng lợi ích là không thể phủ nhận. Thời gian xây dựng nhanh hơn dẫn đến các nhà phát triển hạnh phúc hơn, nhanh nhẹn hơn và cuối cùng, mã tốt hơn.


9

Một ngôn ngữ được biên dịch sẽ luôn đòi hỏi một chi phí ban đầu lớn hơn một ngôn ngữ được dịch. Ngoài ra, có lẽ bạn đã không cấu trúc mã C ++ của mình rất tốt. Ví dụ:

#include "BigClass.h"

class SmallClass
{
   BigClass m_bigClass;
}

Biên dịch chậm hơn rất nhiều so với:

class BigClass;

class SmallClass
{
   BigClass* m_bigClass;
}

3
Đặc biệt đúng nếu BigClass xảy ra để bao gồm thêm 5 file mà nó sử dụng, cuối cùng bao gồm tất cả các mã trong chương trình của bạn.
Tom Leys

7
Đây có lẽ là một lý do. Nhưng Pascal chẳng hạn chỉ mất một phần mười thời gian biên dịch mà một chương trình C ++ tương đương mất. Điều này không phải vì tối ưu hóa gcc: s mất nhiều thời gian hơn mà là Pascal dễ phân tích cú pháp hơn và không phải xử lý bộ tiền xử lý. Cũng xem trình biên dịch Digital Mars D.
Daniel O

2
Đây không phải là phân tích cú pháp dễ dàng hơn, đó là tính mô đun giúp tránh diễn giải lại windows.h và có nhiều tiêu đề khác cho mỗi đơn vị biên dịch. Đúng, Pascal phân tích cú pháp dễ dàng hơn (mặc dù những người trưởng thành, như Delphi lại phức tạp hơn), nhưng đó không phải là điều làm nên sự khác biệt lớn.
Marco van de Voort

1
Kỹ thuật trình bày ở đây trong đó cung cấp một sự cải tiến về tốc độ tổng hợp được gọi là tờ khai chuyển tiếp .
DavidRR

viết các lớp chỉ trong một tập tin. nó sẽ không phải là mã lộn xộn?
Fennekin

8

Một cách dễ dàng để giảm thời gian biên dịch trong các dự án C ++ lớn hơn là tạo tệp * .cpp bao gồm tất cả các tệp cpp trong dự án của bạn và biên dịch nó. Điều này làm giảm vấn đề nổ tiêu đề xuống một lần. Ưu điểm của việc này là các lỗi biên dịch vẫn sẽ tham chiếu đúng tệp.

Ví dụ: giả sử bạn có a.cpp, b.cpp và c.cpp .. tạo một tệp: every.cpp:

#include "a.cpp"
#include "b.cpp"
#include "c.cpp"

Sau đó biên dịch dự án bằng cách chỉ everything.cpp làm


3
Tôi không thấy sự phản đối của phương pháp này. Giả sử bạn tạo bao gồm từ tập lệnh hoặc Makefile, đó không phải là vấn đề bảo trì. Trong thực tế, nó tăng tốc độ biên dịch mà không làm xáo trộn các vấn đề biên dịch. Bạn có thể tranh luận mức tiêu thụ bộ nhớ khi biên dịch nhưng điều đó hiếm khi là một vấn đề trên máy hiện đại. Vì vậy, đối tượng của phương pháp này là gì (ngoài khẳng định rằng nó sai)?
rileyberton

9
@rileyberton (kể từ khi ai đó nêu lên nhận xét của bạn) hãy để tôi đánh vần nó: không, nó không tăng tốc độ biên dịch. Trong thực tế, nó đảm bảo rằng bất kỳ trình biên dịch nào cũng mất thời gian tối đa bằng cách không cách ly các đơn vị dịch thuật. Điều tuyệt vời ở họ là, bạn không cần phải biên dịch lại tất cả .cpp-s nếu chúng không thay đổi. (Đó là coi thường các lập luận phong cách). Quản lý phụ thuộc thích hợp và có lẽ tiêu đề biên dịch sẵn được nhiều hơn tốt hơn nhiều.
sehe

7
Xin lỗi, nhưng đây có thể là một phương pháp rất hiệu quả để tăng tốc độ biên dịch, bởi vì bạn (1) loại bỏ khá nhiều liên kết và (2) chỉ phải xử lý các tiêu đề thường được sử dụng một lần. Ngoài ra, nó hoạt động trong thực tế , nếu bạn bận tâm để thử nó. Thật không may, nó làm cho việc xây dựng lại gia tăng là không thể, vì vậy mọi công trình đều hoàn toàn từ đầu. Nhưng việc xây dựng lại hoàn toàn với phương pháp này nhanh hơn rất nhiều so với những gì bạn nhận được
jalf

4
@BartekBanachewicz chắc chắn, nhưng những gì bạn nói là "nó không tốc độ biên soạn lên", không có vòng loại. Như bạn nói, nó làm cho mỗi biên dịch lấy số tiền tối đa thời gian (không xây dựng lại một phần), nhưng đồng thời, nó làm giảm đáng kể mức tối đa so với những gì nó muốn khác được. Tôi chỉ nói rằng đó là một chút nhiều sắc thái hơn là "không làm điều này"
jalf

2
Hãy vui vẻ với các biến và chức năng tĩnh. Nếu tôi muốn một đơn vị biên dịch lớn, tôi sẽ tạo một tệp .cpp lớn.
gnasher729

6

Một số lý do là:

1) Ngữ pháp C ++ phức tạp hơn C # hoặc Java và mất nhiều thời gian hơn để phân tích cú pháp.

2) (Quan trọng hơn) Trình biên dịch C ++ tạo mã máy và thực hiện tất cả các tối ưu hóa trong quá trình biên dịch. C # và Java chỉ đi được một nửa và để các bước này cho JIT.


5

Sự đánh đổi mà bạn đang nhận được là chương trình chạy nhanh hơn một chút. Đó có thể là một sự thoải mái lạnh lùng với bạn trong quá trình phát triển, nhưng nó có thể là vấn đề lớn khi quá trình phát triển hoàn tất và chương trình chỉ được điều hành bởi người dùng.


4

Hầu hết các câu trả lời đều không rõ ràng khi đề cập rằng C # sẽ luôn chạy chậm hơn do chi phí thực hiện các hành động mà trong C ++ chỉ được thực hiện một lần tại thời điểm biên dịch, chi phí hiệu năng này cũng bị ảnh hưởng do phụ thuộc thời gian chạy (có thể tải thêm nhiều thứ để có thể để chạy), chưa kể các chương trình C # sẽ luôn có dung lượng bộ nhớ cao hơn, tất cả dẫn đến hiệu suất có liên quan chặt chẽ hơn với khả năng của phần cứng khả dụng. Điều này cũng đúng với các ngôn ngữ khác được diễn giải hoặc phụ thuộc vào VM.


4

Có hai vấn đề tôi có thể nghĩ rằng có thể ảnh hưởng đến tốc độ biên dịch chương trình của bạn trong C ++.

VẤN ĐỀ SỐ 1 - GIẢI QUYẾT TRỤ SỞ: (Điều này có thể hoặc chưa được giải quyết bằng một câu trả lời hoặc nhận xét khác.) Microsoft Visual C ++ (AKA VC ++) hỗ trợ các tiêu đề được biên dịch trước, tôi rất khuyến khích. Khi bạn tạo một dự án mới và chọn loại chương trình bạn đang thực hiện, một cửa sổ trình hướng dẫn thiết lập sẽ xuất hiện trên màn hình của bạn. Nếu bạn nhấn nút Tiếp theo> Nút ở dưới cùng của nó, cửa sổ sẽ đưa bạn đến một trang có một số danh sách các tính năng; đảm bảo rằng hộp bên cạnh tùy chọn Tiêu đề được biên dịch trước được chọn lọc. (LƯU Ý: Đây là kinh nghiệm của tôi với các ứng dụng bảng điều khiển Win32 trong C ++, nhưng điều này có thể không đúng với tất cả các loại chương trình trong C ++.)

VẤN ĐỀ SỐ 2 - VỊ TRÍ ĐƯỢC TẠO RA: Mùa hè này, tôi đã tham gia một khóa học lập trình và chúng tôi phải lưu trữ tất cả các dự án của chúng tôi trên các ổ đĩa flash 8GB, vì các máy tính trong phòng thí nghiệm chúng tôi đang sử dụng bị xóa sạch mỗi đêm vào nửa đêm, mà sẽ xóa tất cả công việc của chúng tôi. Nếu bạn đang biên dịch sang một thiết bị lưu trữ ngoài vì mục đích di động / bảo mật / v.v., nó có thể mất một nhiều thời gianthời gian (ngay cả với các tiêu đề biên dịch sẵn mà tôi đã đề cập ở trên) cho chương trình của bạn để biên dịch, đặc biệt nếu đó là một chương trình khá lớn. Lời khuyên của tôi cho bạn trong trường hợp này là tạo và biên dịch các chương trình trên ổ cứng của máy tính bạn đang sử dụng và bất cứ khi nào bạn muốn / cần ngừng làm việc với (các) dự án của bạn vì bất kỳ lý do gì, hãy chuyển chúng sang bên ngoài của bạn thiết bị lưu trữ, sau đó nhấp vào biểu tượng Phần cứng loại bỏ phần cứng và Eject Media, xuất hiện dưới dạng một ổ flash nhỏ phía sau một vòng tròn nhỏ màu xanh lá cây có dấu kiểm màu trắng trên đó, để ngắt kết nối.

Tôi hy vọng cái này sẽ giúp bạn; Hãy cho tôi biết nếu nó làm! :)

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.