Внутренняя и внешняя защита

Я слышал, что вы должны предпочесть писать внутренние включающие охранники вместо внешних включающих охранников.
Я искал в Интернете, но не нашел ответа на него.

Это фрагмент книги 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, Но, проверив его внешне, компилятор может вообще не открывать файл.
Рекомендуется только внешне проверять, включен ли заголовочный файл из других заголовочных файлов.
Проверка не требуется при включении из исходного файла.


Заключение:

  • Внутренняя охрана гарантирует правильность
  • Внешняя защита может улучшить скорость компиляции на некоторых компиляторах
    • Затраты заключаются в том, чтобы поставить проверку повсеместно, чтобы заголовочный файл был включен в другой заголовочный файл и правильно произнес бы имя защитного символа. Поэтому не является предпочтительным.
Другие вопросы по тегам