Có phải #pragma đã từng là một phần của tiêu chuẩn C ++ 11?


140

Theo truyền thống, cách tiêu chuẩn và di động để tránh nhiều vùi tiêu đề trong C ++ là / sử dụng #ifndef - #define - #endiflược đồ chỉ thị tiền biên dịch còn được gọi là lược đồ bảo vệ macro (xem đoạn mã bên dưới).

#ifndef MY_HEADER_HPP
#define MY_HEADER_HPP
...
#endif

Tuy nhiên, trong hầu hết các triển khai / trình biên dịch (xem hình bên dưới), có một sự thay thế "thanh lịch" hơn, phục vụ cho cùng một mục đích như sơ đồ bảo vệ vĩ mô được gọi #pragma once. #pragma oncecó một số lợi thế so với sơ đồ bảo vệ vĩ mô, bao gồm ít mã hơn, tránh xung đột tên và đôi khi cải thiện tốc độ biên dịch.

nhập mô tả hình ảnh ở đây

Thực hiện một số nghiên cứu, tôi nhận ra rằng mặc dù #pragma oncechỉ thị được hỗ trợ bởi hầu hết tất cả các trình biên dịch đã biết, nhưng có một sự mơ hồ về việc liệu #pragma oncechỉ thị có phải là một phần của tiêu chuẩn C ++ 11 hay không.

Câu hỏi:

  • Ai đó có thể làm rõ liệu #pragma oncechỉ thị có phải là một phần của tiêu chuẩn C ++ 11 hay không?
  • Nếu nó không phải là một phần của tiêu chuẩn C ++ 11, có kế hoạch nào để đưa nó vào các bản phát hành sau (ví dụ: C ++ 14 trở lên) không?
  • Sẽ rất tốt nếu ai đó có thể giải thích thêm về những lợi thế / bất lợi trong việc sử dụng một trong các kỹ thuật (nghĩa là bảo vệ vĩ mô so với #pragma once).

9
Ngẫu nhiên, việc sử dụng dấu gạch dưới kép cho bộ bảo vệ tiêu đề bị cấm theo tiêu chuẩn, dự trữ cho việc thực hiện tất cả các biểu tượng bắt đầu bằng dấu gạch dưới kép (bên cạnh các ký tự khác).
Matteo Italia

9
Sử dụng một dấu gạch dưới hàng đầu theo sau là một chữ in hoa cũng bị cấm. Thứ hai, độ đục ở đâu? Tôi chỉ thấy hỗ trợ trình biên dịch, tôi thấy không ai tuyên bố nó là một phần của tiêu chuẩn?
Yakk - Adam Nevraumont

1
Đối với gạch đầu dòng thứ ba, hãy xem câu hỏi liên quan: Có phải #pragma một khi an toàn bao gồm bảo vệ? Nó có một tình huống mà các vệ sĩ tiêu đề làm việc nhưng #pragma oncethường thì không.
dùng1942027

1
có thể trùng lặp ở chỗ nó trả lời câu hỏi này mà không đề cập đến C ++ 11.
Yakk - Adam Nevraumont

3
Vâng, nó không được mã hóa trong bất kỳ tài liệu chính thức nào, nhưng bạn có thể coi nó là tiêu chuẩn thực tế .
Siyuan Ren

Câu trả lời:


107

#pragma oncekhông chuẩn. Nó là một phần mở rộng rộng rãi (nhưng không phổ biến), có thể được sử dụng

  • nếu mối quan tâm về tính di động của bạn bị hạn chế, và
  • bạn có thể chắc chắn rằng tất cả các tệp bao gồm của bạn luôn nằm trên một đĩa cục bộ.

Nó đã được xem xét để tiêu chuẩn hóa, nhưng bị từ chối vì nó không thể được thực hiện một cách đáng tin cậy. (Sự cố xảy ra khi bạn có các tệp có thể truy cập thông qua một số gắn kết từ xa khác nhau.)

Khá dễ dàng để đảm bảo rằng không có xung đột bảo vệ bao gồm trong một phát triển. Đối với các thư viện, có thể được sử dụng bởi nhiều phát triển khác nhau, giải pháp rõ ràng là tạo ra nhiều ký tự ngẫu nhiên cho bộ bảo vệ bao gồm khi bạn tạo nó. (Một trình soạn thảo tốt có thể được thiết lập để làm điều này cho bạn bất cứ khi nào bạn mở một tiêu đề mới.) Nhưng ngay cả khi không có điều này, tôi vẫn chưa gặp phải bất kỳ vấn đề nào với xung đột giữa các thư viện.


11
Không chỉ gắn kết từ xa. Liên kết cứng, liên kết mềm, cấu trúc trạm biến áp (trên Windows). Nó có thể thực sự lộn xộn.
Tonny

45
Tại sao trình biên dịch không thể sử dụng tổng kiểm tra SHA-1 hoặc MD5 để xác định các tệp?
Serge

29
Tôi thực sự không thấy vấn đề gì khi không đưa thứ gì đó vào tiêu chuẩn nếu mọi trình biên dịch chính hỗ trợ nó. Có những thứ thực sự trong tiêu chuẩn ít được hỗ trợ hơn thế này. Ngoài ra, có vẻ khá ngớ ngẩn khi phàn nàn về các vấn đề cạnh, khi chúng ta đang nói về việc bao gồm các tệp, trong đó xung đột tên tệp đã là một vấn đề lớn. Sẽ thật tuyệt nếu nhu cầu này đối với tính năng không có vấn đề 100% đã được áp dụng cho khái niệm về các tệp tiêu đề #included nói chung.
TED

38
Nếu mã của bạn bao gồm một số tệp từ các vị trí khác nhau thông qua các liên kết tượng trưng hoặc gắn kết kỳ lạ thì nó đã không khả dụng. Do đó, tranh luận rằng pragma oncekhông thể thực hiện một cách hợp lý một cái gì đó vốn không phải là di động (và thậm chí không nên xem xét) là một điều vô nghĩa khác của C ++ đảo lộn thế giới.
tài liệu

7
@JoseAntonioDuraOlmos Tôi đồng ý rằng các liên kết tượng trưng là một tính năng của hệ điều hành, nằm ngoài phạm vi của ngôn ngữ C ++. Do đó, câu hỏi đặt ra tại sao C ++ comitee nên xem xét một cái gì đó nằm ngoài phạm vi của ngôn ngữ? Cố gắng đảm bảo một cái gì đó không phải là trách nhiệm của họ không có ý nghĩa gì IMO. DOS chỉ hỗ trợ 8 + 3 ký tự cho mỗi tên tệp, nhưng không ai tranh luận rằng #includephải xóa, bởi vì người ta có thể sử dụng sai lệnh một cách mù quáng. #pragma oncekhông hạn chế tính di động theo bất kỳ cách nào, miễn là bạn sẽ không khai thác các liên kết tượng trưng để phá vỡ quá trình biên dịch.
doc

32

Mục §16.6 của Tiêu chuẩn ( dự thảo N3936 ) mô tả các #pragmachỉ thị như:

Một chỉ thị tiền xử lý của mẫu

# pragma pp-tokensopt new-line

làm cho việc thực hiện hành xử theo cách xác định thực hiện. Hành vi có thể khiến bản dịch bị lỗi hoặc khiến người dịch hoặc chương trình kết quả hành xử theo cách không tuân thủ. Bất kỳ pragma không được công nhận bởi việc thực hiện được bỏ qua.

Về cơ bản #pragma oncelà một ví dụ cụ thể thực hiện của một lệnh #pragma, và không, nó không phải là tiêu chuẩn. Chưa.

Nó thường được hỗ trợ rộng rãi bởi hầu hết các "trình biên dịch chính" bao gồm GCCClang và do đó đôi khi được khuyến nghị để tránh nồi hơi bảo vệ bao gồm.


10
Lưu ý rằng bạn có thể cả hai #pragma#definebảo vệ tiêu đề.
Yakk - Adam Nevraumont

18
"Bất kỳ pragma nào không được công nhận bởi việc thực hiện đều bị bỏ qua" . Có nghĩa là thông báo: Cảnh báo: chỉ thị pragma không được công nhận là không tuân thủ?
Rodrigo

6
"và do đó là cách được khuyến nghị để tránh nồi hơi bảo vệ bao gồm" - một tuyên bố rất táo bạo. Đó là một cách không chuẩn, và lợi ích của việc sử dụng nó là rất ít và hầu như không liên quan đến kinh nghiệm của tôi, vì vậy tôi đã phải lấy +1 của mình.
Alex

19
@Yakk: Nếu ai đó viết #definetiêu đề bảo vệ, anh ấy / cô ấy KHÔNG có lý do để viết #pragma oncelà tốt.
Nawaz

5
@Nawaz Trình biên dịch có thể giữ bộ đệm của mọi tệp (theo đường dẫn) đã được #pragma onced và trong trường hợp nó #includelại d có thể bỏ qua #include(thậm chí không mở tệp). gcc làm tương tự với các vệ sĩ tiêu đề, nhưng nó rất, rất dễ vỡ. Các #pragmamột rất dễ dàng để làm, là bảo vệ tiêu đề rất khó.
Yakk - Adam Nevraumont
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.