В чем причина того, что #pragma Once находится внутри защитных ограждений заголовка?

Только что видел это внутри <boost/asio.hpp>

#ifndef BOOST_ASIO_HPP
#define BOOST_ASIO_HPP

#if defined(_MSC_VER) && (_MSC_VER >= 1200)
# pragma once
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)

/// ....

#endif // BOOST_ASIO_HPP

Не обращая внимания на проверки препроцессора _MSC_VER, в чем преимущество использования #pragma once в этом случае? Разве защита заголовка препроцессора не гарантирует, что во всех случаях и на всех платформах содержимое заголовка всегда included один раз?


person dubnde    schedule 13.08.2010    source источник


Ответы (5)


#pragma once указывает, что файл будет включен (открыт) только один раз компилятором при компиляции файла с исходным кодом. Это может сократить время сборки, поскольку компилятор не будет открывать и читать файл после первого #include модуля.

Если вы этого не сделаете #pragma once, файл будет открываться каждый раз, когда это необходимо, и компилятор прекратит анализировать его на #ifndef BOOST_ASIO_HPP, если он был определен.

person Aoi Karasu    schedule 13.08.2010
comment
Вы говорите, что заголовок открывается и читается только один раз, если у нас есть #pragma? Защита заголовков означает, что файл всегда открывается, но содержимое внутри средств защиты пропускается, верно? Я правильно понимаю? Если бы я только мог продемонстрировать это, чтобы увидеть, как это происходит :) - person dubnde; 13.08.2010
comment
В случае #pragma once он не всегда открывается. Эта директива заставляет компилятор помнить, что не следует открывать его снова (более одного раза). Вот почему эта директива превосходит #ifndef, которую можно было бы опустить. Однако многие люди по-прежнему используют #ifndef для поддержки старых компиляторов, которые ни разу не распознают #pragma. - person Aoi Karasu; 13.08.2010

Указывает, что файл будет включен (открыт) только один раз компилятором в сборку . Это может сократить время сборки, поскольку компилятор не будет открывать и читать файл после первого #include модуля.

И еще один связанный с этим вопрос от SO

person DumbCoder    schedule 13.08.2010
comment
в порядке. Я понимаю такое предназначение защиты жатки. Вопрос в том, почему у нас есть защита заголовка и прагма один - person dubnde; 13.08.2010
comment
@MeThinks - возможно, не все реализации поддерживают эту прагму, поэтому вы все равно хотите, чтобы ваш заголовок не обрабатывался несколько раз. Дополнительным преимуществом здесь является прагма. - person ysap; 13.08.2010
comment
На многие из них дан ответ в ссылке SO, которую я дал в ответе. - person DumbCoder; 13.08.2010

Да, защита заголовков гарантирует, что содержимое заголовка будет включено только один раз. но здесь вы используете #pragma для проверки другого определения, а не для включения файла.

Приведенная ниже ссылка - это существующий вопрос о защите заголовков в SO.

Назначение защиты заголовков

person ckv    schedule 13.08.2010
comment
Охрана заголовка все равно это делает, верно? зачем еще раз нужна #pragma? - person dubnde; 13.08.2010
comment
Защита заголовка сообщает препроцессору, что он должен отключить все строки в файле от #ifndef до #endif, но предполагается, что препроцессор читает весь файл и просто не выводит результат для блока. #pragma once сообщает препроцессору, что все последующие #include, содержащие тот же файл, должны игнорироваться. Разница в том, что в последнем случае препроцессор даже не откроет файл и не проверит. При этом #pragma once не является стандартом, и компиляторы научились понимать шаблон защиты включения, и особой разницы быть не должно. - person David Rodríguez - dribeas; 13.08.2010
comment
@MeThinks - возможно, не все реализации поддерживают эту прагму, поэтому вы все равно хотите, чтобы ваш заголовок не обрабатывался несколько раз. Дополнительным преимуществом здесь является прагма. (комментарий дублирован из другого ответа) - person ysap; 13.08.2010

#pragma once имеет ту же цель, но средства защиты предназначены для более глубокого анализа, чтобы гарантировать, что файл включен ровно один раз - например,

// somerandomfileinmyproject.cpp
#undef BOOST_ASIO_HPP 
#include <bost/asio.cpp>

Если компилятор не обрабатывает такие случаи правильно, ему все равно необходимо открыть файл и передать его через препроцессор, даже если он был включен ранее.

person peterchen    schedule 13.08.2010

Вы можете воспроизвести эффект #pragma once стандартным способом, используя следующее:

#if !defined GUARD_SYMBOL
#include "GUARDED_FILE"
#endif

хотя он гораздо более подробный. Как говорили другие, это помогает сократить время компиляции, поскольку файл не ищется / не открывается вместо того, чтобы открывать файл и игнорировать все внутри него - файл все еще должен быть проанализирован препроцессором.

person Skizz    schedule 13.08.2010
comment
Как отметил Дэвид выше, большинство современных компиляторов (особенно gcc) достаточно хорошо понимают шаблон защиты заголовка, чтобы пропустить часть повторного анализа и действовать так, как если бы прагма была однажды или как если бы код был написан так, как вы здесь показываете. Это, а также тот факт, что прагма однажды не может правильно обрабатывать некоторые угловые случаи, также является причиной того, почему прагма однажды была активно отклонена от включения в новый стандарт C ++ 0x. см. также это обсуждение SO - person Fabio Fracassi; 13.08.2010