Внутренняя и внешняя защита
Я слышал, что вы должны предпочесть писать внутренние включающие охранники вместо внешних включающих охранников.
Я искал в Интернете, но не нашел ответа на него.
Это фрагмент книги C++ Standards от Herb & Andrei "Стандарты кодирования", в которой показана "внешняя защита включения":
Избегайте использования устаревших внешних защитных устройств, защищенных в старых книгах:
#ifndef FOO_HJNCLUDED_ //NOT recommended
#include "foo.h"
#define FOO_HJNCLUDED_
#endif
Теперь это приводит к вопросу ниже:
В: Что такое внутренняя защита включения и что такое внешняя защита включения? В чем разница между ними, и почему предпочтительны внутренние охранники?
Я хотел бы, чтобы ответ также привести пример.
Редактировать: я закончил тем, что отвечал на мой собственный вопрос.
2 ответа
Вот то, что я видел, что, вероятно, объясняет комментарий.
Вот, foo.h
определяет "внутреннюю защиту включения" (для большинства людей ее просто сокращают до "включения защиты", поскольку это традиционный способ сделать это).
// foo.h
#ifndef _FOO_H__
#define _FOO_H__
// ...
#endif // _FOO_H__
По сравнению, bar.h
использует foo.h
Включите охрану вне foo.h
, Мы можем назвать это как "внешний включающий охранник".
// bar.h
#ifndef _BAR_H__
#define _BAR_H__
#ifndef _FOO_H__
#include "foo.h"
#endif
// ...
#endif // _BAR_H__
Один (очень большой) проект, над которым я работал, утверждал, что это увеличило скорость компиляции, но утверждение сомнительно, так как это кажется мне тривиальной оптимизацией компилятора, и я не видел ни одной метрики, подтверждающей утверждение. Тем не менее, мы заметили, что чтение нескольких файлов заголовков раздражает.
Хорошо покопавшись, теперь я могу ответить на свой вопрос.
Внутренняя защита:
Распространенная идиома, заключающаяся в том, что "включить охрану" вокруг содержимого включаемых заголовочных файлов:
header.h
#ifndef HEADER_H
#define HEADER_H
// Contents of include file
#endif
Поэтому содержимое заголовка будет обработано один раз, даже если заголовок #include
Эд несколько раз.
Это известно как "внутренняя защита включения", потому что защита полностью внутренняя по отношению к заголовочному файлу.
Внешняя защита:
Тем не менее, может возникнуть проблема с вышеуказанным методом, если компилятор использует простой подход, открывая файл несколько раз, чтобы проверить наличие "внутренних защитных вставок", которые могут привести к увеличению времени компиляции в больших проектах.
header2.h
#ifndef HEADER_H
#include "header.h"
#endif
// Rest of header file goes here
Линия: #ifndef HEADER_H
все еще определяется и проверяется внутри header.h
, Но, проверив его внешне, компилятор может вообще не открывать файл.
Рекомендуется только внешне проверять, включен ли заголовочный файл из других заголовочных файлов.
Проверка не требуется при включении из исходного файла.
Заключение:
- Внутренняя охрана гарантирует правильность
- Внешняя защита может улучшить скорость компиляции на некоторых компиляторах
- Затраты заключаются в том, чтобы поставить проверку повсеместно, чтобы заголовочный файл был включен в другой заголовочный файл и правильно произнес бы имя защитного символа. Поэтому не является предпочтительным.