Compartilhar via


Limpar Inclusões do C/C++ no Visual Studio

A partir do Visual Studio 17.8 Versão Prévia 1, o Visual Studio fornece um recurso de limpeza de #include que melhora a qualidade do seu código das seguintes maneiras:

  • Oferece a adição de arquivos de cabeçalho para código que é compilado apenas porque um arquivo de cabeçalho necessário foi incluído indiretamente por outro arquivo de cabeçalho.
  • Oferece a remoção de arquivos de cabeçalho não utilizados, melhorando os tempos de compilação e a limpeza do código.

O Include Cleanup está ativado por padrão. Para saber como configurá-la, confira Configurar C/C++ Include Cleanup no Visual Studio.

Cabeçalhos diretos versus indiretos

Primeiro, algumas terminologias:

  • Um cabeçalho direto é um cabeçalho que você #include explicitamente no seu código.
  • Um cabeçalho indireto é um cabeçalho que você não #include explicitamente. Em vez disso, um arquivo de cabeçalho que você inclui diretamente o inclui. Também dizemos que um cabeçalho indireto está incluído transitively.

O Include Cleanup analisa seu código e determina quais cabeçalhos não são utilizados e quais foram incluídos indiretamente. Considere o seguinte arquivo de cabeçalho:

// myHeader.h

#include <string>
#include <iostream>

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

E o programa que o utiliza:

// 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 é um cabeçalho direto porque myProgram.cpp o inclui explicitamente. myHeader.h inclui <string> e <iostream>, portanto, eles são cabeçalhos indiretos.

O problema é que myProgram.cpp usa std::string e std::cout, mas não inclui diretamente os cabeçalhos que os definem. Esse código é compilado porque myHeader.h inclui esses cabeçalhos. Esse código é frágil porque se myHeader.h parasse de incluir qualquer um deles, myProgram.cpp não compilaria mais.

De acordo com as diretrizes do C++, é melhor incluir explicitamente cabeçalhos para todas as dependências para que o código não esteja sujeito à fragilidade causada por alterações nos arquivos de cabeçalho. Para obter mais informações, confira Diretrizes Principais do C++ SF.10.

O Include Cleanup analisa o código para identificar cabeçalhos não utilizados e incluídos indiretamente. Ele fornece comentários com base nas configurações descritas em Configurar a ferramenta C++ #include no Visual Studio. Os comentários podem estar na forma de avisos de lista de erros, sugestões etc. Para obter mais detalhes sobre os comentários fornecidos pelo Include Cleanup, confira Mensagens do Include Cleanup.

Cabeçalhos não utilizados

À medida que o código evolui, talvez você não precise mais de alguns arquivos de cabeçalho. Isso é difícil de acompanhar em um projeto complexo. Com o tempo, as compilações podem demorar mais porque o compilador está processando arquivos de cabeçalho desnecessários. O Include Cleanup ajuda você a localizar e remover os cabeçalhos não utilizados. Por exemplo, e se myFunc() for comentado em 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
}

Na captura de tela a seguir, #include "myHeader.h" está esmaecido (uma configuração descrita em Configurar a ferramenta do C++ #include no Visual Studio) porque não é utilizado desde que myFunc() foi comentado.

Passe o cursor sobre o #include esmaecido para abrir o menu de ação rápida. Clique na lâmpada (ou escolha o link Mostrar possíveis correções) para ver as ações relacionadas ao arquivo não utilizado:

Three refactoring options are shown: Remove # include myHeader.h, remove all unused includes, and Add all transitively used and remove all unused # includes.

Adicionar cabeçalhos utilizados de forma transitiva

Poderíamos optar por remover o arquivo de cabeçalho não utilizado, mas isso quebra o código, pois <string> e <iostream> foram incluídos indiretamente por meio de myheader.h.

Em vez disso, podemos optar por Adicionar todos os #includes utilizados de forma transitiva e remover todos os não utilizados. Isso remove o cabeçalho não utilizado myHeader.h, mas também adiciona todos os cabeçalhos que estão sendo utilizados que foram incluídos indiretamente por meio de myHeader.h. Nesse caso, o resultado é adicionar #include <string> e #include <iostream> a myProgram.cpp e remover #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();
}

A ferramenta não atualiza os comentários, mas você pode ver que o código está usando std::string e std::cout diretamente. Esse código não é mais frágil porque não depende de myHeader.h para incluir os outros cabeçalhos necessários.

Melhor prática

Não remova os que parecem ser arquivos de cabeçalho não utilizados, sem primeiro adicionar os arquivos de cabeçalho incluídos indiretamente. Isso ocorre porque o código pode depender de inclusões indiretas em um arquivo de cabeçalho que, de outra forma, não é utilizado. Adicionar cabeçalhos utilizados de forma transitiva primeiro. Em seguida, quando você remove cabeçalhos não utilizados, você não obtém erros de compilação devido a arquivos de cabeçalho ausentes que foram incluídos indiretamente por um arquivo de cabeçalho que você removeu.

Uma maneira de fazer isso é definir a configuração do Include Cleanup para o nível de sugestão de Adicionar inclusões ausentes como Sugestão (Ferramentas>Opções>Editor de Texto>C/C++>Limpeza de Código). Defina também o nível de sugestão de Remover inclusões não utilizadas como Sugestão. Em seguida:

  1. Na lista de erros, verifique se o filtro está definido como Compilar + IntelliSense.
  2. Procure instâncias de "Conteúdo de #include x foi utilizado neste arquivo e incluído de forma transitiva".
  3. Passe o cursor sobre uma linha com a sugestão. Na lista suspensa de lâmpadas, selecione Adicionar todas as inclusões utilizadas de forma transitiva.
  4. Repita essas etapas no seu projeto até que todas as sugestões sobre inclusões transitivas sejam abordadas.
  5. Remover inclusões não utilizadas: na lista de erros, procure uma instância de "o #include x não foi utilizado neste arquivo".
  6. Passe o cursor sobre o cabeçalho não utilizado. Na lista suspensa de lâmpadas, selecione Remover todas as inclusões não utilizadas.
  7. Repita essas etapas no seu projeto até que todas as sugestões do Include Cleanup sejam abordadas.

Nesta breve visão geral, você viu como o Include Cleanup pode ajudar a remover cabeçalhos não utilizados e adicionar cabeçalhos que foram incluídos indiretamente. Isso ajuda você a manter o código limpo, possivelmente compilar mais rápido e reduzir a fragilidade do código.

Confira também

Configurar o C/C++ Include Cleanup no Visual Studio
Mensagens do Include Cleanup