2010-08-13 37 views
18

Chỉ cần nhìn thấy điều này trong <boost/asio.hpp>Lý do cho #pragma một khi nằm trong bộ phận bảo vệ tiêu đề là gì?

#ifndef BOOST_ASIO_HPP 
#define BOOST_ASIO_HPP 

#if defined(_MSC_VER) && (_MSC_VER >= 1200) 
# pragma once 
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) 

/// .... 

#endif // BOOST_ASIO_HPP 

Bất chấp các _MSC_VER kiểm tra tiền xử lý, lợi ích của việc có các #pragma once trong trường hợp này là gì? Không bảo vệ tiêu đề tiền xử lý đảm bảo trong mọi trường hợp và trên tất cả các nền tảng, nội dung tiêu đề chỉ bao giờ là included một lần?

Trả lời

21

#pragma once xác định rằng các tập tin sẽ được bao gồm (mở) chỉ một lần bởi trình biên dịch khi soạn thảo một tập tin mã nguồn. Điều này có thể giảm thời gian xây dựng vì trình biên dịch sẽ không mở và đọc tệp sau #include đầu tiên của mô-đun.

Nếu bạn không #pragma once, tệp sẽ là mở mỗi lần cần thiết và trình biên dịch sẽ ngừng phân tích cú pháp trên #ifndef BOOST_ASIO_HPP, nếu nó đã được xác định.

+0

Bạn nói tiêu đề được mở và chỉ đọc một lần nếu chúng tôi có #pragma? Bảo vệ tiêu đề có nghĩa là tệp luôn được mở nhưng nội dung trong phạm vi bảo vệ bị bỏ qua, phải không? Tôi hiểu có đúng không? Nếu tôi chỉ có thể chứng minh điều này vì vậy tôi thấy nó xảy ra :) – dubnde

+1

Trong trường hợp #pragma một khi nó không phải lúc nào cũng được mở ra. Chỉ thị này làm cho trình biên dịch nhớ không mở lại (nhiều lần). Đó là lý do tại sao chỉ thị này vượt trội hơn #ifndef, có thể bỏ qua. Tuy nhiên nhiều người vẫn sử dụng #ifndef để hỗ trợ các trình biên dịch cũ mà không nhận ra #pragma một lần. –

0

Có bảo vệ tiêu đề đảm bảo rằng nội dung tiêu đề chỉ được bao gồm một lần. nhưng ở đây bạn đang sử dụng #pragma để kiểm tra định nghĩa khác và không bao gồm tệp.

Liên kết dưới đây là câu hỏi hiện có về bộ phận bảo vệ tiêu đề trong SO.

Purpose of Header guards

+1

Trình bảo vệ đầu trang thực hiện việc này, đúng không? tại sao cần #pragma một lần nữa? – dubnde

+4

Trình bảo vệ tiêu đề cho bộ tiền xử lý biết rằng nó phải tắt tất cả các dòng trong tập tin từ '# ifndef' thành' # endif', nhưng bộ tiền xử lý được giả định đọc toàn bộ tệp và chỉ xuất kết quả cho khối đó. '#pragma once' thông báo cho bộ tiền xử lý rằng bất kỳ' # include' nào có chứa cùng một tập tin sẽ bị bỏ qua. Sự khác biệt là trong trường hợp sau, bộ tiền xử lý thậm chí sẽ không mở tệp và kiểm tra. Điều đó đang được nói, '#pragma once' không phải là tiêu chuẩn, và các trình biên dịch đã phát triển để hiểu được mô hình bảo vệ bao gồm và không nên có nhiều sự khác biệt. –

+0

@MeThinks - có thể không phải tất cả các triển khai đều hỗ trợ pragma này, vì vậy bạn vẫn muốn ngăn tiêu đề của mình bị xử lý nhiều lần. Pragma là một lợi ích bổ sung ở đây. (bình luận trùng lặp từ một câu trả lời khác) – ysap

3
+1

Tại sao bỏ phiếu xuống? – DumbCoder

+1

ok. Tôi hiểu mục đích của các vệ sĩ tiêu đề.Câu hỏi là tại sao chúng ta có header guard và pragma – dubnde

+1

@MeThinks - có lẽ không phải tất cả các triển khai đều hỗ trợ pragma này, vì vậy bạn vẫn muốn ngăn tiêu đề của mình bị xử lý nhiều lần. Pragma là một lợi ích bổ sung ở đây. – ysap

0

#pragma once có cùng mục đích, nhưng bao gồm các nhân viên bảo vệ được yêu cầu phân tích sâu hơn để đảm bảo tệp được bao gồm chính xác một lần - ví dụ:

// somerandomfileinmyproject.cpp 
#undef BOOST_ASIO_HPP 
#include <bost/asio.cpp> 

Trừ khi trình biên dịch xử lý các trường hợp này một cách chính xác, nó vẫn cần mở tệp và chuyển nó qua bộ xử lý trước mặc dù đã được bao gồm trước đó.

0

Bạn có thể tái tạo các hiệu ứng của #pragma once trong một cách tiêu chuẩn sử dụng như sau:

#if !defined GUARD_SYMBOL 
#include "GUARDED_FILE" 
#endif 

mặc dù nó là nhiều hơn nữa tiết. Như những người khác đã nói, nó giúp với thời gian biên dịch kể từ khi các tập tin không được tìm kiếm/mở thay vì mở tập tin và bỏ qua tất cả mọi thứ bên trong nó - tập tin vẫn phải được phân tích cú pháp bởi bộ tiền xử lý.

+1

Như David đã lưu ý ở trên, hầu hết các trình biên dịch hiện đại (esp. Gcc) đều hiểu được mẫu bảo vệ đầu trang đủ tốt để bỏ qua phần reparsing, và hành động như thể có một pragma một lần hoặc như mã được viết theo cách bạn hiển thị ở đây. Điều này, và thực tế là pragma một lần không thể xử lý chính xác một số trường hợp góc cũng là lý do tại sao pragma một lần đã bị từ chối chủ động từ việc đưa vào tiêu chuẩn C++ 0x mới. cũng xem [SO disscussion] này (http://stackoverflow.com/questions/787533/is-pragma-once-a-safe-include-guard) –

Các vấn đề liên quan