Là thư viện chỉ tiêu đề hiệu quả hơn?


48

Giả định

  1. Một trong những lợi thế của các thư viện chỉ dành cho tiêu đề cho C ++ là chúng không cần phải được biên dịch riêng.

  2. Trong C và C ++ inlinechỉ có ý nghĩa nếu hàm được xác định trong tệp tiêu đề *.

  3. Theo truyền thống, trong bố cục C, .c / .h đã được sử dụng, trong đó tiêu đề đại diện cho giao diện chung tối thiểu của đơn vị dịch thuật. Tương tự, .cpp / hpp.

Câu hỏi

Các thư viện chỉ tiêu đề thường có mã hiệu quả hơn và thời gian thực hiện khôn ngoan hơn so với bố cục truyền thống? Nếu vậy, điều này là do nội tuyến mở rộng hoặc tối ưu hóa khác?

* - việc xác định hàm trong một tiêu đề cho phép trình biên dịch thấy việc triển khai trong quá trình biên dịch của bất kỳ đơn vị dịch thuật nào và thực tế có thể thực hiện mã nội tuyến


2
Bạn sẽ ngạc nhiên khi có rất nhiều trình liên kết C ++ hiện đại (GCC, MSVC, ICC, v.v.) có thể mã nội tuyến trên các đơn vị dịch thuật riêng biệt. Tôi sẽ nói "nói chung là không" trên quan điểm hiệu quả với số lần tối ưu hóa các trình liên kết đã bất chấp sự mong đợi của tôi và quản lý theo cách nào đó (ngoại trừ bối cảnh dylib trong đó đặt nội tuyến trong tiêu đề hoặc cung cấp triển khai trong thư viện liên kết tĩnh riêng biệt có thể giúp đỡ) . Tuy nhiên, các thư viện chỉ có tiêu đề, miễn là chúng ổn định cả về giao diện và triển khai, có thể gợi cảm vì chúng có thể được triển khai dễ dàng như thế nào trong các dự án mới.

1
Tôi không biết rằng điều này xứng đáng có câu trả lời đầy đủ, nhưng một lợi ích to lớn của libs chỉ là tiêu đề dễ cài đặt và sử dụng: Tải xuống, #include "lib.h (pp)", đã được thực hiện.
WeRelic

Câu trả lời:


44

Một trong những lợi thế của các thư viện chỉ dành cho tiêu đề cho C ++ là chúng không cần phải được biên dịch riêng

Không, đó không phải là một lợi thế, hoàn toàn ngược lại - phần chính của thư viện phải được biên soạn thường xuyên khi được đưa vào, không chỉ một lần. Điều đó thường sẽ tăng thời gian biên dịch. Tuy nhiên, nếu bạn đang đề cập đến những lợi thế được liệt kê ở đây trong Wikipedia : bài báo đó đang nói về việc giảm chi phí quản trị liên quan đến toàn bộ quá trình xây dựng, đóng gói và triển khai.

Trong C và C ++ nội tuyến chỉ có ý nghĩa nếu chức năng được xác định trong tệp tiêu đề *

Điều này phụ thuộc vào hệ thống trình biên dịch / trình liên kết, nhưng tôi đoán đối với hầu hết các trình biên dịch C và C ++ hiện tại thì điều này là đúng.

Theo truyền thống, trong bố cục C, .c / .h đã được sử dụng, trong đó tiêu đề đại diện cho giao diện chung tối thiểu của đơn vị dịch thuật. Tương tự, .cpp / hpp.

Điều đó chủ yếu là chính xác. Các tiêu đề lớp C ++ thường chứa nhiều hơn giao diện chung tối thiểu - chúng thường chứa rất nhiều nội dung riêng tư. Để giảm thiểu điều này, những thứ như thành ngữ PIMPL được sử dụng. Đây là một cái gì đó giống như "đối diện" của một thư viện chỉ tiêu đề, nó cố gắng giảm thiểu nội dung tiêu đề cần thiết.

Nhưng để trả lời câu hỏi chính của bạn: đây là một sự đánh đổi. Càng nhiều mã thư viện đặt vào các tệp tiêu đề, trình biên dịch càng có cơ hội tối ưu hóa mã cho tốc độ (nếu điều này thực sự xảy ra hoặc nếu sự gia tăng là đáng chú ý, là một câu hỏi hoàn toàn khác). Mặt khác, quá nhiều mã trong các tiêu đề làm tăng thời gian biên dịch. Đặc biệt trong các dự án C ++ lớn, điều này có thể trở thành một vấn đề nghiêm trọng, xem "Thiết kế phần mềm C ++ quy mô lớn" của John Lakos - mặc dù cuốn sách hơi lỗi thời và một số vấn đề được mô tả trong đó được giải quyết bởi các trình biên dịch hiện đại, những ý tưởng chung / giải pháp vẫn còn hiệu lực.

Đặc biệt, khi bạn không sử dụng thư viện ổn định (bên thứ ba), nhưng bạn đang phát triển libs của riêng mình trong dự án của bạn, thời gian biên dịch trở nên rõ ràng. Mỗi khi bạn thay đổi một cái gì đó trong lib, bạn phải thay đổi một tệp tiêu đề, điều này sẽ gây ra một biên dịch lại và liên kết của tất cả các đơn vị phụ thuộc.

IMHO sự phổ biến của libs chỉ tiêu đề được gây ra bởi sự phổ biến của lập trình meta mẫu. Đối với hầu hết các trình biên dịch, libs templated phải chỉ có tiêu đề vì trình biên dịch chỉ có thể bắt đầu quá trình biên dịch chính khi các tham số loại được cung cấp, và để biên dịch và tối ưu hóa đầy đủ, trình biên dịch phải xem "cả hai cùng một lúc" - mã thư viện cộng với mẫu giá trị tham số. Điều đó khiến cho không thể (hoặc ít nhất là khó) tạo ra bất kỳ đơn vị biên dịch "tiền biên dịch" nào cho một thư viện như vậy.


6
Vì vậy, trong ngắn hạn, các thư viện chỉ tiêu đề là thuận tiện hơn là hiệu quả hơn ; và vì C ++ không có bất kỳ trình quản lý gói tiêu chuẩn nào, điều này giúp thúc đẩy việc áp dụng.
Matthieu M.

6
@MatthieuM: không, mã được biên dịch đôi khi có thể hiệu quả hơn và đối với các mẫu lib, thiết kế chỉ tiêu đề thường không phải là một câu hỏi về sự thuận tiện. Và tăng thời gian biên dịch chắc chắn không thuận tiện hơn.
Doc Brown

Có mã nóng trong các tiêu đề thực sự có thể dẫn đến một mã được biên dịch hiệu quả hơn, tuy nhiên điều này không yêu cầu phải có tất cả các mã trong các tiêu đề và do đó độc lập, IMHO, từ các thư viện chỉ có tiêu đề.
Matthieu M.

1
@MatthieuM.: Điều đó chắc chắn là đúng, tuy nhiên tôi nghĩ thuật ngữ "thuận tiện hơn" không mô tả đúng về trường hợp này.
Doc Brown

3
Tôi đã làm việc trong một dự án nhúng lớn trên hệ điều hành cũ, mỏng hơn cho chủ nhân trước đây của tôi và trong những trường hợp đó tôi có thể chứng thực nỗi đau của thời gian biên dịch dài. Bất cứ ai bị bắt nhồi quá nhiều vào các tập tin tiêu đề sẽ bị xử lý không thương tiếc.
Fred Thomsen

15

Chà, trước tiên hãy phá hủy một số giả định của bạn:

  1. Một trong những lợi thế của các thư viện chỉ dành cho tiêu đề cho C ++ là chúng không cần phải được biên dịch riêng.

Biên dịch mọi thứ một cách riêng biệt có nghĩa là có khả năng không phải biên dịch lại mọi thứ nếu chỉ một phần thay đổi.
Vì vậy, một bất lợi thay vì một lợi thế.

  1. Trong C và C ++ nội tuyến chỉ có ý nghĩa nếu chức năng được xác định trong tệp tiêu đề *.

Có, hiệu ứng duy nhất inlinecòn lại là ngoại lệ cho quy tắc một định nghĩa .
Khốn cho bạn nếu những định nghĩa đó khác nhau theo bất kỳ cách nào.

Vì vậy, nếu một hàm là nội bộ cho một đơn vị biên dịch, hãy đánh dấu nó static. Điều đó cũng làm cho nội tuyến có nhiều khả năng hơn, vì chức năng cần phải có sẵn để nội tuyến nó.
Tuy nhiên, hãy xem tối ưu hóa thời gian liên kết, như được hỗ trợ bởi ít nhất MSVC ++, gcc và clang.

  1. Theo truyền thống, trong bố cục C, .c / .h đã được sử dụng, trong đó tiêu đề đại diện cho giao diện chung tối thiểu của đơn vị dịch thuật. Tương tự, .cpp / hpp.

Chà, chỉ trình bày giao diện tối thiểu chắc chắn là một trong những mục tiêu, để đạt được độ ổn định API và ABI cao hơn và để giảm thiểu thời gian biên dịch.

Đặc biệt là các lớp C ++ không thực sự hướng đến điều đó, vì tất cả các bit riêng tư bị rò rỉ vào tiêu đề, cũng như các lớp được bảo vệ cho dù bạn có muốn lấy từ nó hay không.

PIMPL mẫu thiết kế là để giảm các chi tiết như vậy.

Mặc dù phần tách giao diện và triển khai hoàn toàn thất bại trong C ++ là các mẫu.
Ủy ban đã cố gắng làm một cái gì đó với các mẫu xuất khẩu , nhưng điều đó đã bị bỏ qua vì quá phức tạp và không thực sự hoạt động.

Bây giờ, họ đang làm việc trên một hệ thống mô-đun thích hợp , mặc dù nó hoạt động chậm. Điều đó làm giảm đáng kể thời gian biên dịch và cũng sẽ tăng tính ổn định của API và ABI bằng cách giảm bề mặt của chúng.

Các thư viện chỉ tiêu đề thường có mã hiệu quả hơn và thời gian thực hiện khôn ngoan hơn so với bố cục truyền thống? Nếu vậy, điều này là do nội tuyến mở rộng hoặc tối ưu hóa khác?

Các thư viện chỉ dành cho tiêu đề có thể hiệu quả hơn về kích thước mã và thời gian thực hiện, mặc dù điều đó phụ thuộc vào việc thư viện có được chia sẻ hay không, sử dụng bao nhiêu, theo cách nào và liệu nội tuyến có chứng minh chiến thắng quyết định trong trường hợp cụ thể đó hay không.

Và lý do nội tuyến rất quan trọng đối với việc tối ưu hóa không phải vì bản thân nội tuyến là một sự thúc đẩy lớn như vậy, nhưng do các cơ hội để truyền bá liên tục và tối ưu hóa hơn nữa, nó mở ra.

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.