#pragma once

Нередко (см. обсуждение на BoostDev, StackOverflow) поднимается вопрос о том, каким образом лучше оформлять .h файлы. Использовать ли стандартный метод «стражей включения», нестандартную, но поддерживаемую большинством компиляторов директиву #pragma once или же комбинацию и того и другого (и если комбинировать, то что ставить в начале файла). Я сам нередко колебался между этими вариантами в своём коде и сейчас решил изложить свою текущую точку зрения.

Преимущества #pragma once

  • Ускорение компиляции, так как не надо повторно прогонять файл через препроцессор (тем не менее, современные компиляторы (например, GCC) нередко способны распознать наличие стражей включения, в таком случае #pragma once уже не даст ускорения).
  • Чище код: одна короткая строчка вместо трёх, две из которых — длинные.
  • Не надо выдумывать название макроса. Макрос может привести к конфликту имён. Например, при переносе содержимого в другой файл можно забыть поменять имя макроса, и, в случае дублирования, нужный файл не будет включён, а это трата нервов на поиски невнятных ошибок компиляции.

Недостатки #pragma once

  • Нет поддержки стандартами C и C++, следовательно, компилятор не обязан понимать эту директиву. По стандарту неподдерживаемая pragma должна быть проигнорирована, и, скорее всего, компилятор не выдаст даже предупреждения, что, опять же, может привести к невнятным ошибкам компиляции вроде «переопределения символа». Ещё хуже, если компилятор будет вкладывать в #pragma once совсем иной смысл (такие примеры мне не известны, но всё же)…

Указанный недостаток можно частично побороть, скомбинировав стражи включения с #pragma once. При этом рекомендуется размещать #ifndef/#define в самом начале файла даже до комментариев, а #endif размещать последней строчкой (возможно существование компиляторов, которые проводят минимальный предварительный анализ файлов, поэтому такое размещение увеличивает вероятность ускорения компиляции сферическим компилятором в вакууме).

Нежелание комитета по стандартизации включить #pragma once в стандарт C++ вызывает сожаление. Не C, а именно C++, потому что в случае «чистого» си минимальный компилятор может быть действительно маленьким, что может быть важно на определённых платформах. В случае же стандартного C++ или, тем более, C++11, компилятор маленьким быть не может заведомо, он обречён быть своеобразным программным «монстром». Большинство компиляторов её и так уже поддерживают (мне не известны современные компиляторы C++, не поддерживающие #pragma once). Мотивация вида «у нас уже есть стандартный метод» никуда не годится, потому что этот «стандартный метод» очевидный overkill/костыль и не лишён недостатков (иногда даже бывает так).

Итак, на данный момент я использую #pragma once без стражей включения в C++ коде. Я использую стражи включения без #pragma once в переносимом plain C коде.

Реклама

One response

  1. […] смирился. Я больше не толкаю везде #pragma once. Мне недавно раскрыли глаза касательно возможности […]

Добавить комментарий

Заполните поля или щелкните по значку, чтобы оставить свой комментарий:

Логотип WordPress.com

Для комментария используется ваша учётная запись WordPress.com. Выход / Изменить )

Фотография Twitter

Для комментария используется ваша учётная запись Twitter. Выход / Изменить )

Фотография Facebook

Для комментария используется ваша учётная запись Facebook. Выход / Изменить )

Google+ photo

Для комментария используется ваша учётная запись Google+. Выход / Изменить )

Connecting to %s

%d такие блоггеры, как: