В языках программирования Си и C++ #pragma once — нестандартная, но широко распространенная препроцессорная директива, разработанная для контроля за тем, чтобы конкретный исходный файл при компиляции подключался строго один раз. То есть, #pragma once
применяется для тех же целей, что и include guard, но требует меньше кода и не допускает возможности коллизии имён. В наборе компиляторов GCC до версии 3.4 считалась устаревшей и для применения не рекомендовалась.[1] Однако из-за широкого применения это решение было изменено.[2]
В статье об include guard приводится пример ситуации, в которой нужно использовать тот или иной метод. Выходом является использование include guard, приведенное там же; Вариантом использования #pragma once
может быть:
#pragma once
struct foo {
int member;
};
#include "grandfather.h"
#include "grandfather.h"
#include "father.h"
Компилятор | #pragma once |
---|---|
Clang | Да[3] |
Comeau C/C++ | Да [4] |
C++Builder XE3 | Да[5] |
Digital Mars C++ | Да[6] |
GCC | Да[7] (с версии 3.4[8]) |
HP C/aC++ | Да[9] (по крайней мере с версии A.06.12) |
IBM XL C/C++ | Да[10] (с версии 13.1.1) |
Intel C++ Compiler | Да[11] |
Microsoft Visual C++ | Да[12] (с версии 4.2) |
Pelles C | Да[13] |
ARM DS-5 | Да[14] |
IAR C/C++ | Да[15] |
Solaris Studio C/C++ | Нет [16][17] |
Применение #pragma once
вместо include guard увеличит скорость компиляции во многих случаях благодаря высокоуровневому механизму; компилятор может самостоятельно сравнивать имена файлов или inode'ы без необходимости вызова препроцессора Си для проверки заголовка на наличие #ifndef
и #endif
.
С другой стороны, некоторые компиляторы, как например, GCC, также используют специальный код для распознавания и оптимизации обработки include guard.[1]
Из-за того, что компилятор сам по себе отвечает за обработку #pragma once
, программисту нет необходимости создавать новые имена, например, GRANDFATHER_H
. Это исключает риск коллизии имён, то есть заголовочный файл не сможет вызвать ошибку при его подключении. Также приходится меньше набирать текста, нежели при использовании include guard.
Тем не менее, такая высокоуровневая обработка ускоряется в обоих случаях, но программисту приходится полагаться на корректную обработку компилятором #pragma once
. Если компилятор совершает ошибку, например, не может распознать ситуацию, когда две символьные ссылки с различными именами указывают на один и тот же файл, то компиляция завершается с ошибкой. Компиляторами, содержащими ошибки, связанные с #pragma once
, являются LCC-Win32 версии 2004 года[18][19] и GCC версии 1998 года.[1] GCC первоначально выдавал предупреждение об отключении #pragma once
, если компилируемый код использовал её. Тем не менее, в релизе 3.4 GCC код обработки команды #pragma once
был исправлен для корректной работы с символьными и жёсткими ссылками. Данная возможность была сочтена полезной и предупреждение было убрано.[20][21]
Можно использовать обе команды, #pragma once
и include guards, для написания переносимого кода, что также может принести выгоду от применения #pragma once
при оптимизации (если компилятор её поддерживает):
#pragma once
#ifndef GRANDFATHER_H
#define GRANDFATHER_H
struct foo
{
int member;
};
#endif /* GRANDFATHER_H */
Данная страница на сайте WikiSort.ru содержит текст со страницы сайта "Википедия".
Если Вы хотите её отредактировать, то можете сделать это на странице редактирования в Википедии.
Если сделанные Вами правки не будут кем-нибудь удалены, то через несколько дней они появятся на сайте WikiSort.ru .