Tradycyjnie, standardowym i przenośnym sposobem uniknięcia wielu włączeń nagłówków w C ++ było / jest użycie #ifndef - #define - #endif
schematu dyrektyw prekompilatora, zwanego również schematem ochrony makr (zobacz fragment kodu poniżej).
#ifndef MY_HEADER_HPP
#define MY_HEADER_HPP
...
#endif
Jednak w większości implementacji / kompilatorów (patrz rysunek poniżej) istnieje bardziej „elegancka” alternatywa, która służy temu samemu celowi, co schemat ochrony makro #pragma once
. #pragma once
ma kilka zalet w porównaniu ze schematem ochrony makr, w tym mniej kodu, unikanie kolizji nazw, a czasami poprawioną szybkość kompilacji.
Po przeprowadzeniu pewnych badań zdałem sobie sprawę, że chociaż #pragma once
dyrektywa jest obsługiwana przez prawie wszystkie znane kompilatory, istnieje niejasność dotycząca tego, czy #pragma once
dyrektywa jest częścią standardu C ++ 11, czy nie.
Pytania:
- Czy ktoś mógłby wyjaśnić, czy
#pragma once
dyrektywa jest częścią standardu C ++ 11, czy nie? - Jeśli nie jest częścią standardu C ++ 11, czy są jakieś plany włączenia go w późniejszych wersjach (np. C ++ 14 lub nowszych)?
- Byłoby również miło, gdyby ktoś mógł bardziej szczegółowo omówić zalety / wady stosowania którejkolwiek z technik (tj. Makroostrożność kontra
#pragma once
).
#pragma once
zwykle nie.Odpowiedzi:
#pragma once
nie jest standardem. Jest to szeroko rozpowszechnione (ale nie uniwersalne) rozszerzenie, z którego można korzystaćBył brany pod uwagę pod kątem normalizacji, ale odrzucony, ponieważ nie można go niezawodnie wdrożyć. (Problemy występują, gdy masz pliki dostępne przez kilka różnych zdalnych montowań).
Dość łatwo jest upewnić się, że nie ma konfliktów włączania zabezpieczeń w ramach jednego rozwoju. W przypadku bibliotek, które mogą być używane przez wiele różnych programów, oczywistym rozwiązaniem jest wygenerowanie wielu losowych znaków dla funkcji włączania strażnika podczas jej tworzenia. (Można ustawić dobry edytor, który zrobi to za Ciebie za każdym razem, gdy otworzysz nowy nagłówek.) Ale nawet bez tego nie napotkałem jeszcze żadnych problemów z konfliktami między bibliotekami.
źródło
pragma once
nie można przenośnie zaimplementować czegoś, co z natury nie jest przenośne (i nie powinno być nawet brane pod uwagę), to kolejny nonsens C ++ do góry nogami.#include
należy to usunąć, ponieważ można ślepo nadużywać dyrektywy.#pragma once
nie ogranicza w żaden sposób przenośności, pod warunkiem, że nie będziesz wykorzystywać dowiązań symbolicznych do przerywania kompilacji.Sekcja §16.6 normy ( projekt N3936 ) opisuje
#pragma
dyrektywy jako:Zasadniczo
#pragma once
jest to instancja#pragma
dyrektywy specyficzna dla implementacji i nie, nie jest to standard. Jeszcze.Często jest szeroko obsługiwany przez większość "głównych kompilatorów", w tym GCC i Clang, dlatego czasami zaleca się unikanie standardowej wersji include-guards.
źródło
#pragma
i#define
strażnika nagłówka.#define
ochronę nagłówka, to też NIE ma powodu, żeby pisać#pragma once
.#pragma once
d, aw przypadku, gdy jest to#include
ponownie d, może pominąć#include
(nawet nie otwierać pliku). gcc robi to samo z ochroną nagłówków, ale jest bardzo, bardzo delikatne. Ten#pragma
jest łatwy do zrobienia, ochrona nagłówka jest trudna.