Один типичный пример для использования volatile
должен использовать volatile boolean
переменная как флаг для завершения потока. Если Вы запустили поток, и Вы хотите быть в состоянии безопасно прервать его от различного потока, у Вас может быть поток, периодически проверяют флаг. Для остановки его установите флаг на истинный. Путем создания флага volatile
, можно удостовериться, что поток, который проверяет его, будет видеть, что это было установлено в следующий раз, когда это проверяет его, не имея необходимость даже использовать synchronized
блок.
Я не думаю, что это существенно повлияет на время компиляции, но #pragma once
очень хорошо поддерживается компиляторами, но фактически не является частью стандарта. Препроцессор может работать с ним немного быстрее, так как с ним проще понять ваше точное намерение.
#pragma once
менее подвержена ошибкам и требует меньше кода.
Для ускорения компиляции. time more просто пересылайте объявление вместо включения в файлы .h, когда можете.
Я предпочитаю использовать #pragma один раз
.
См. Эту статью в википедии о возможности использования обоих .
Если вы уверены, что никогда не будете использовать этот код в компиляторе, который его не поддерживает (Windows / VS, GCC и Clang - примеры компиляторов, которые поддерживают ), то вы можете без проблем использовать #pragma один раз.
Вы также можете просто использовать оба (см. Пример ниже), чтобы получить переносимость и ускорение компиляции на совместимых системах
#pragma once
#ifndef _HEADER_H_
#define _HEADER_H_
...
#endif
Пока #pragma once
не станет стандартным (в настоящее время это не является приоритетом для будущих стандартов), я предлагаю вам использовать его И использовать охранники, это путь:
#ifndef BLAH_H
#define BLAH_H
#pragma once
// ...
#endif
Причины:
#pragma once
не является стандартным, поэтому возможно, что какой-то компилятор не предоставляет эту функциональность. Тем не менее, его поддерживают все основные компиляторы. Если компилятор этого не знает, по крайней мере, он будет проигнорирован. #pragma once
не существует, не следует предполагать, что поведение будет одинаковым для всех компиляторов. Охрана гарантирует, что, по крайней мере, основное предположение одинаково для всех компиляторов, которые, по крайней мере, реализуют необходимые инструкции препроцессора для защиты. #pragma once
ускорит компиляцию (одного cpp), потому что компилятор не будет повторно открывать файл, содержащий эту инструкцию. Так что наличие его в файле может помочь или нет, в зависимости от компилятора. Я слышал, что g ++ может производить такую же оптимизацию при обнаружении охранников, но это должно быть подтверждено. Используя их вместе, вы получаете лучшее от каждого компилятора.
Теперь, если у вас нет какого-либо автоматического скрипта для создания охранников, может быть удобнее просто использовать #pragma один раз
. Просто знайте, что это значит для переносимого кода. (Я использую VAssistX для быстрой генерации охранников и прагмы)
Вы почти всегда должны думать о своем коде переносимым способом (потому что вы не знаете, из чего сделано будущее), но если вы действительно думаете, что это не предназначено для компиляции с другим компилятором (например, код для очень специфического встроенного оборудования), тогда вам следует просто проверить документацию компилятора о #pragma once
, чтобы узнать, что вы действительно делаете.
Обычно я не беспокоюсь о #pragma once
, так как мой код иногда приходится компилировать с чем-то, кроме MSVC или GCC (компиляторы для встроенных систем не всегда есть #pragma).
Так что я все равно должен использовать #include охранников. Я также мог бы использовать #pragma once
, как предлагают некоторые ответы, но, похоже, нет особых причин, и это часто вызывает ненужные предупреждения на компиляторах, которые его не поддерживают.
Я не уверен, какую экономию времени может принести прагма. Я слышал, что компиляторы обычно уже распознают, когда в заголовке нет ничего, кроме комментариев вне защитных макросов, и в этом случае будут выполнять эквивалент #pragma once
(т. Е. Никогда не обрабатывать файл снова). Но я не уверен, что это
Думаю, первое, что вам нужно сделать, это проверить, действительно ли это имеет значение, т.е. вы должны сначала проверить производительность. Один из поисковых запросов в Google вызвал это .
На странице результатов столбцы для меня слегка отключены, но ясно, что по крайней мере до VC6 Microsoft не реализовывала оптимизацию защиты включения, которая другие инструменты использовали. Если защита включения была внутренней, это заняло в 50 раз больше времени по сравнению с внешней защитой включения (внешние средства защиты по крайней мере так же хороши, как #pragma). Но давайте рассмотрим возможные последствия этого:
Согласно представленным таблицам, время открытия включения и проверки в 50 раз больше, чем у эквивалента #pragma. Но фактическое время для этого было измерено в 1 микросекунду на файл еще в 1999 году!
Итак, сколько дублированных заголовков будет у одного TU? Это зависит от вашего стиля, но если мы скажем, что в среднем TU имеет 100 дубликатов, то в 1999 году мы потенциально платим 100 микросекунд за TU. С улучшением жестких дисков это, вероятно, значительно ниже, но даже тогда с предварительно скомпилированными заголовками и правильным отслеживанием зависимостей общая совокупная стоимость этого для проекта почти наверняка будет незначительной частью вашего времени сборки.
Теперь, с другой стороны, , как бы маловероятно это ни было, если вы когда-нибудь перейдете к компилятору, который не t support #pragma once
затем подумайте, сколько времени потребуется, чтобы обновить всю вашу исходную базу, чтобы включить охранники, а не #pragma?
Нет причин, по которым Microsoft не может реализовать оптимизацию защиты включения так же, как GCC и любой другой компилятор (на самом деле, может ли кто-нибудь подтвердить, реализуют ли это его более свежие версии?). IMHO, #pragma once
мало что делает, кроме ограничения вашего выбора альтернативного компилятора.
#pragma once
позволяет компилятору полностью пропустить файл, когда он повторяется снова, вместо того, чтобы анализировать файл до тех пор, пока он не достигнет #include guards.
Таким образом, семантика немного отличаются, но они идентичны, если они используются так, как они предназначены для использования.
Объединение обоих, вероятно, является самым безопасным путем, как в худшем случае (компилятор помечает неизвестные прагмы как фактические ошибки, не только предупреждения), вам просто нужно удалить сами прагмы #.
Когда вы ограничиваете свои платформы, скажем, "основные компиляторы на рабочем столе", вы можете спокойно опустить #include guards, но я чувствую себя неловко тоже.
ОТ: если у вас есть другие советы / впечатления по ускорению сборки, мне было бы любопытно.