Очистка C/C++ включается в Visual Studio

Начиная с Visual Studio 17.8 (предварительная версия 1), Visual Studio предоставляет #include функцию очистки, которая улучшает качество кода следующим образом:

Visual Studio предоставляет #include функцию очистки, которая улучшает качество кода следующим образом:

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

Параметр «Включать очистку» по умолчанию отключен. Сведения о том, как его настроить, см. в статье Настройка очистки включаемых файлов Config C/C++ в Visual Studio.

Прямые и косвенные заголовки

Некоторые термины:

  • Прямой заголовок — это заголовок, который вы явно #include в своём коде.
  • Непрямой заголовочный файл включён, потому что его включает заголовочный файл, который вы подключаете напрямую. Вы также можете сказать, что косвенный заголовок включён transitively.

Include Cleanup анализирует ваш код и определяет, какие заголовочные файлы не используются, а какие включаются косвенно. Рассмотрим следующий файл заголовка:

// myHeader.h

#include <string>
#include <iostream>

void myFunc()
{
    std::string s = "myFunc()\n";
    std::cout << s;
}

И программа, использующая ее:

// myProgram.cpp
#include "myHeader.h"

int main()
{
    std::string s = "main()"; // string is indirectly included by myHeader.h
    std::cout << s; // cout is indirectly included by myHeader.h
    myFunc();
}

myHeader.h является прямым заголовком, так как myProgram.cpp явно включает его. myHeader.h включает <string> и <iostream>, поэтому это косвенные заголовки.

Проблема заключается в том, что myProgram.cpp использует std::string и std::coutне включает непосредственно заголовки, определяющие их. Этот код компилируется, так как myHeader.h включает эти заголовки. Этот код хрупок, потому что если myHeader.h когда-нибудь перестанет включать хотя бы один из них, myProgram.cpp больше не скомпилируется.

В соответствии с рекомендациями C++ лучше явно включать заголовки для всех зависимостей, чтобы код не подвергался хрупкости, вызванной изменениями файлов заголовков. Дополнительные сведения см. в руководстве SF.10: Избегайте зависимостей от неявно #includeобъявленных имен в C++ Core Guidelines.

Include Cleanup анализирует ваш код, чтобы выявлять неиспользуемые и косвенно подключаемые заголовочные файлы. Он предоставляет отзывы на основе параметров, описанных в разделе "Настройка средства #include C++ в Visual Studio". Обратная связь поступает в виде предупреждений и рекомендаций в списке ошибок. Дополнительные сведения об отзывах, предоставляемых Include Cleanup, см. в разделе Сообщения Include Cleanup.

Неиспользуемые заголовки

По мере развития кода вам больше не потребуется некоторые файлы заголовков. Трудно отслеживать эти заголовки в сложном проекте. Со временем сборки могут занять больше времени, так как компилятор обрабатывает ненужные файлы заголовков. Включение очистки помогает находить и удалять неиспользуемые заголовки. Например, что будет, если вы закомментируете myFunc() в myProgram.cpp:

// myProgram.cpp
#include "myHeader.h"

int main()
{
    std::string s = "main()"; // string is indirectly included from myHeader.h
    std::cout << s; // cout is indirectly included from myHeader.h
    // myFunc(); // directly included from myHeader.h
}

На следующем снимке экрана #include "myHeader.h" отображается неактивным (параметр, описанный в разделе «Настройка средства C++ #include в Visual Studio»), поскольку в нём больше нет необходимости, так как myFunc() закомментирован.

Наведите указатель мыши на затемнённый элемент #include, чтобы открыть меню быстрых действий. Выберите лампочку (или выберите ссылку "Показать потенциальные исправления"), чтобы просмотреть действия, связанные с неиспользуемым файлом:

Показаны три варианта рефакторинга: удалить #include myHeader.h, удалить все неиспользуемые директивы #include и добавить все транзитивно используемые и удалить все неиспользуемые директивы #include.

Добавление транзитивно используемых заголовков

Вы можете удалить неиспользуемый файл заголовка, но это действие ломает код, так как <string> и <iostream> косвенно включаются через myheader.h.

Вместо этого можно выбрать Добавить все транзитивно используемые и удалить все неиспользуемые директивы #include. Это удаляет неиспользуемый заголовок myHeader.h, но также добавляет все используемые заголовки, которые косвенно включаются через myHeader.h. Результат в данном случае — добавление #include <string> и #include <iostream> в myProgram.cpp и удаление #include "myHeader.h":

// myProgram.cpp
#include <iostream>
#include <string>

int main()
{
    std::string s = "main()"; // string is directly included from <string>
    std::cout << s; // cout is directly included from <string>
    // MyFunc();
}

Инструмент не обновляет комментарии, но видно, что код теперь использует std::string и std::cout напрямую. Этот код больше не хрупкий, так как он не зависит от того, что myHeader.h включает другие обязательные заголовки.

Рекомендуемая практика

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

Одним из способов этого является следующее:

  • Задайте для параметра Include Cleanup значение Предложение для уровня предложений для добавления отсутствующих директив #include (Сервис>Параметры>Текстовый редактор>C/C++>Code Cleanup).
  • Установка "Удалить неиспользуемое" включает уровень предложения в предложение.

Одним из способов этого является следующее:

  • Задайте раскрывающийся список для параметра "Очистка включения", чтобы выбрать, как выделить отсутствующие операторы #include, которые транзитивно включены в предложение(>параметры>всех параметров>языков>C/C++>Code cleanup>).
  • Установите для параметра Выберите способ выделения директив #include, которые не используются значение Рекомендация.

Затем:

  1. В списке ошибок убедитесь, что для фильтра задано значение Build + IntelliSense.
  2. Найдите случаи, где «содержимое из #include x используется в этом файле и подключается транзитивно».
  3. Наведите указатель мыши на строку с предложением. В раскрывающемся списке лампочки выберите "Добавить все транзитивно использованные" элементы.
  4. Повторяйте эти шаги в вашем проекте, пока не будут устранены все рекомендации, касающиеся транзитивных включений.
  5. Удалите неиспользуемые директивы include: в списке ошибок найдите сообщение "#include x не используется в данном файле."
  6. Наведите указатель мыши на неиспользуемый заголовок. В раскрывающемся списке лампочки выберите " Удалить все неиспользуемые" элементы.
  7. Повторяйте эти шаги в вашем проекте, пока не будут обработаны все предложения Include Cleanup.

В этом кратком обзоре вы узнали, как включить очистку можно удалить неиспользуемые заголовки и добавить заголовки, которые были косвенно включены. Этот процесс помогает обеспечить очистку кода, потенциально ускорить сборку и снизить уровень ломки кода.

См. также

Настройка очистки включения C/C++ в Visual Studio
Включить сообщения очистки