Чи є #pragma колись частиною стандарту C ++ 11?


140

Традиційно стандартним та портативним способом уникнути декількох включень заголовків у C ++ було / є використання #ifndef - #define - #endifсхеми директив попереднього компілятора, яка також називається макрозахисною схемою (див. Фрагмент коду нижче).

#ifndef MY_HEADER_HPP
#define MY_HEADER_HPP
...
#endif

У більшості реалізацій / компіляторів (див. Малюнок нижче), однак, є більш "елегантна" альтернатива, яка виконує ті ж цілі, що і названа схема макрозахисту #pragma once. #pragma onceУ порівнянні зі схемою макрозахисту є кілька переваг, включаючи менше коду, уникнення сутичок імен та іноді покращену швидкість компіляції.

введіть тут опис зображення

Провівши деякі дослідження, я зрозумів, що хоча #pragma onceдиректива підтримується майже всіма відомими компіляторами, існує помутніння того, чи #pragma onceє директива частиною стандарту C ++ 11 чи ні.

Запитання:

  • Чи може хтось уточнити, чи #pragma onceє директива частиною стандарту C ++ 11 чи ні?
  • Якщо він не є частиною стандарту C ++ 11, чи є якісь плани щодо його включення до пізніших версій (наприклад, C ++ 14 або новіших версій)?
  • Було б також непогано, якби хтось міг детальніше ознайомитись з перевагами / недоліками у використанні будь-якої з методик (тобто, макро-захист проти #pragma once).

9
Між іншим, використання подвійних підкреслень для захисних заголовків стандартом заборонено, що резервує для реалізації всі символи, починаючи з подвійного підкреслення (крім інших).
Маттео Італія

9
Використання провідного підкреслення, за яким йде велика літера, також заборонено. По-друге, де помутніння? Я просто бачу підтримку компілятора, я не бачу, щоб хтось стверджував, що це частина стандарту?
Якк - Адам Невраумон

1
Для третього пункту погляньте на відповідне питання: чи #pragma один раз безпечний включає охорону? У нас виникла ситуація, коли охоронці заголовків працюють, але #pragma onceзазвичай ні.
користувач1942027

1
можливий дублікат, що він відповідає на це питання, не згадуючи C ++ 11.
Якк - Адам Невраумон

3
Ну, це не кодується в жодному офіційному документі, але ви можете вважати це фактично стандартним.
Сіюань Рен

Відповіді:


107

#pragma onceне є стандартним. Це поширене (але не універсальне) розширення, яке можна використовувати

  • якщо ваші проблеми щодо портативності обмежені, і
  • Ви можете бути впевнені, що всі включені файли завжди знаходяться на локальному диску.

Він був розглянутий для стандартизації, але відхилений, оскільки його неможливо надійно реалізувати. (Проблеми виникають, коли у вас є файли, доступні через декілька різних віддалених кріплень.)

Досить легко забезпечити відсутність включення конфліктів охоронців в рамках однієї розробки. Для бібліотек, які можуть бути використані багатьма різними розробками, очевидним рішенням є створення безлічі випадкових символів для включення варти при його створенні. (Хороший редактор може бути створений для цього, коли ви відкриваєте новий заголовок.) Але навіть без цього я ще не стикаюся з будь-якими проблемами з конфліктами між бібліотеками.


11
Не лише віддалені кріплення. Жорсткі посилання, софтпосилання, субстрати (в Windows). Це може стати справді безладним.
Тонні

45
Чому компілятор не може використовувати контрольні суми SHA-1 або MD5 для ідентифікації файлів?
Сергій

29
Я дійсно не бачу сенсу не ставити щось у стандарт, якщо кожен великий компілятор підтримує це. Є фактично в стандарті набагато менш підтримувані, ніж це. Крім того, здається, дуже нерозумно скаржитися на крайові проблеми, коли ми говоримо про включення файлів, де зіткнення імен файлів вже є величезною проблемою. Було б добре, якби ця вимога на 100% безпроблемну функцію була застосована до концепції взагалі # включених файлів заголовків.
ТЕД

38
Якщо ваш код включає якийсь файл з різних місць через символічні посилання або дивні кріплення, він уже не є портативним. Тому стверджувати, що pragma onceне можна портативно реалізувати те, що за своєю суттю не є портативним (і його навіть не слід розглядати) - це ще одна нісенітниця С ++ перевернутого світу.
doc

7
@JoseAntonioDuraOlmos Я погоджуюся, що символічні посилання є функцією ОС, яка виходить за межі мови C ++. Звідси виникає питання, чому комітет C ++ повинен вважати щось, що не виходить за межі мови? Намагання гарантувати щось, що не є їх відповідальністю, IMO не має сенсу. DOS підтримував лише 8 + 3 символи на ім’я файлу, але ніхто не стверджував, що #includeйого потрібно видалити, оскільки можна наосліп неправильно використовувати директиву. #pragma onceне обмежує переносимість жодним чином, за умови, що ви не будете використовувати символічні посилання для розбиття компіляції.
doc

32

Розділ §16.6 стандарту ( проект N3936 ) описує #pragmaдирективи як:

Директива щодо попередньої обробки форми

# pragma pp-tokensopt new-line

змушує реалізацію поводитись визначеним чином. Поведінка може спричинити збій перекладу або призвести до того, що перекладач або програма, що виникає в результаті, поводяться невідповідно. Будь-яка прагма, яка не розпізнається реалізацією, ігнорується.

В основному #pragma onceце конкретний екземпляр #pragmaдирективи, і ні, це не є стандартом. І все-таки.

Її часто підтримують більшість "великих компіляторів", включаючи GCC та Clang, і тому іноді рекомендується уникати котлоагрегатів.


10
Зверніть увагу , що ви можете як #pragmaі #defineзаголовок-охоронець.
Якк - Адам Невраумон

18
"Будь-яка прагма, яка не розпізнається реалізацією, ігнорується" . Чи означає це, що повідомлення: Попередження: непризнана директива прагми не відповідає?
rodrigo

6
"і тому рекомендований спосіб уникнути котлоагрегату" - дуже сміливе твердження. Це нестандартний спосіб, і переваги його використання мало, і навряд чи є актуальними в моєму досвіді, тому мені довелося зняти +1.
Олексій

19
@Yakk: Якщо хтось пише #defineзаголовка, він також не має підстав писати #pragma once.
Наваз

5
@Nawaz Компілятор може зберігати кеш кожного файлу (шляхом), який був #pragma onced, і у випадку, якщо він #includeзнову d, може пропустити #include(навіть не відкривати файл). gcc робить те ж саме із захисними заголовками, але це дуже, дуже крихко. #pragmaОдин легко зробити, заголовок охоронець один важко.
Якк - Адам Невраумон
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.