我应该如何在大型C ++项目中检测不必要的#include文件?

时间:2021-09-28 10:23:27

I am working on a large C++ project in Visual Studio 2008, and there are a lot of files with unnecessary #include directives. Sometimes the #includes are just artifacts and everything will compile fine with them removed, and in other cases classes could be forward declared and the #include could be moved to the .cpp file. Are there any good tools for detecting both of these cases?

我正在研究Visual Studio 2008中的一个大型C ++项目,并且有很多文件带有不必要的#include指令。有时#includes只是工件,一切都会被删除,但是在其他情况下,类可以向前声明,#include可以移动到.cpp文件。是否有任何好的工具可以检测这两种情况?

20 个解决方案

#1


While it won't reveal unneeded include files, Visual studio has a setting /showIncludes (right click on a .cpp file, Properties->C/C++->Advanced) that will output a tree of all included files at compile time. This can help in identifying files that shouldn't need to be included.

虽然它不会显示不需要的包含文件,但Visual Studio有一个设置/ showIncludes(右键单击.cpp文件,属性 - > C / C ++ - >高级),它将在编译时输出所有包含文件的树。这有助于识别不需要包含的文件。

You can also take a look at the pimpl idiom to let you get away with fewer header file dependencies to make it easier to see the cruft that you can remove.

您还可以查看pimpl习惯用法,以便减少头文件依赖性,从而更轻松地查看可以删除的内容。

#2


PC Lint works quite well for this, and it finds all sorts of other goofy problems for you too. It has command line options that can be used to create External Tools in Visual Studio, but I've found that the Visual Lint addin is easier to work with. Even the free version of Visual Lint helps. But give PC-Lint a shot. Configuring it so it doesn't give you too many warnings takes a bit of time, but you'll be amazed at what it turns up.

PC Lint对此非常有效,它也可以为您找到各种其他愚蠢的问题。它具有可用于在Visual Studio中创建外部工具的命令行选项,但我发现Visual Lint插件更易于使用。即使是免费版的Visual Lint也有帮助。但是给PC-Lint一个机会。配置它以便它不会给你太多的警告需要一点时间,但你会惊讶于它出现了什么。

#3


There's a new Clang-based tool, include-what-you-use, that aims to do this.

有一个新的基于Clang的工具,包括你使用的,旨在实现这一目标。

#4


!!DISCLAIMER!! I work on a commercial static analysis tool (not PC Lint). !!DISCLAIMER!!

!!免责声明!我从事商业静态分析工具(不是PC Lint)。 !!免责声明!

There are several issues with a simple non parsing approach:

简单的非解析方法有几个问题:

1) Overload Sets:

1)过载集:

It's possible that an overloaded function has declarations that come from different files. It might be that removing one header file results in a different overload being chosen rather than a compile error! The result will be a silent change in semantics that may be very difficult to track down afterwards.

重载函数可能具有来自不同文件的声明。可能是删除一个头文件会导致选择不同的重载而不是编译错误!结果将是语义的静默变化,之后可能很难跟踪。

2) Template specializations:

2)模板专业化:

Similar to the overload example, if you have partial or explicit specializations for a template you want them all to be visible when the template is used. It might be that specializations for the primary template are in different header files. Removing the header with the specialization will not cause a compile error, but may result in undefined behaviour if that specialization would have been selected. (See: Visibility of template specialization of C++ function)

与重载示例类似,如果您对模板有部分或显式特化,则希望在使用模板时它们都可见。可能是主模板的特化是在不同的头文件中。使用特化删除标头不会导致编译错误,但如果已选择该特化,则可能导致未定义的行为。 (参见:C ++函数模板特化的可见性)

As pointed out by 'msalters', performing a full analysis of the code also allows for analysis of class usage. By checking how a class is used though a specific path of files, it is possible that the definition of the class (and therefore all of its dependnecies) can be removed completely or at least moved to a level closer to the main source in the include tree.

正如'msalters'所指出的,对代码进行全面分析还可以分析类的使用情况。通过检查文件的特定路径如何使用类,有可能可以完全删除类的定义(以及它的所有依赖性),或者至少移动到更接近包含主要源的级别树。

#5


I don't know of any such tools, and I have thought about writing one in the past, but it turns out that this is a difficult problem to solve.

我不知道有任何这样的工具,我曾考虑过写一篇,但事实证明这是一个难以解决的问题。

Say your source file includes a.h and b.h; a.h contains #define USE_FEATURE_X and b.h uses #ifdef USE_FEATURE_X. If #include "a.h" is commented out, your file may still compile, but may not do what you expect. Detecting this programatically is non-trivial.

假设您的源文件包含a.h和b.h; a.h包含#define USE_FEATURE_X,b.h使用#ifdef USE_FEATURE_X。如果#include“a.h”被注释掉,您的文件仍然可以编译,但可能无法按预期执行。以编程方式检测这一点并非易事。

Whatever tool does this would need to know your build environment as well. If a.h looks like:

无论使用什么工具,您都需要了解构建环境。如果a.h看起来像:

#if defined( WINNT )   #define USE_FEATURE_X#endif

Then USE_FEATURE_X is only defined if WINNT is defined, so the tool would need to know what directives are generated by the compiler itself as well as which ones are specified in the compile command rather than in a header file.

然后仅在定义WINNT时定义USE_FEATURE_X,因此该工具需要知道编译器本身生成哪些指令以及在编译命令中而不是在头文件中指定哪些指令。

#6


Like Timmermans, I'm not familiar with any tools for this. But I have known programmers who wrote a Perl (or Python) script to try commenting out each include line one at a time and then compile each file.

像Timmermans一样,我对此并不熟悉任何工具。但我知道编写Perl(或Python)脚本的程序员尝试一次注释掉每个include行,然后编译每个文件。


It appears that now Eric Raymond has a tool for this.

看来现在Eric Raymond有了这个工具。

Google's cpplint.py has an "include what you use" rule (among many others), but as far as I can tell, no "include only what you use." Even so, it can be useful.

谷歌的cpplint.py有一个“包括你使用的”规则(以及其他许多规则),但据我所知,没有“仅包括你使用的内容”。即便如此,它也很有用。

#7


If you're interested in this topic in general, you might want to check out Lakos' Large Scale C++ Software Design. It's a bit dated, but goes into lots of "physical design" issues like finding the absolute minimum of headers that need to be included. I haven't really seen this sort of thing discussed anywhere else.

如果您对这个主题感兴趣,可能需要查看Lakos的大规模C ++软件设计。这有点过时了,但是会遇到很多“物理设计”问题,例如找到需要包含的标题的绝对最小值。我还没有真正看到其他任何地方讨论过这种事情。

#8


Give Include Manager a try. It integrates easily in Visual Studio and visualizes your include paths which helps you to find unnecessary stuff.Internally it uses Graphviz but there are many more cool features. And although it is a commercial product it has a very low price.

试试Include Manager。它可以在Visual Studio中轻松集成,并可视化您的包含路径,帮助您找到不必要的东西。内部它使用Graphviz但有更多很酷的功能。虽然它是商业产品,但价格非常低廉。

#9


You can build an include graph using C/C++ Include File Dependencies Watcher, and find unneeded includes visually.

您可以使用C / C ++ Include File Dependencies Watcher构建包含图,并直观地查找不需要的包含。

#10


If your header files generally start with

如果您的头文件通常以

#ifndef __SOMEHEADER_H__#define __SOMEHEADER_H__// header contents#endif

(as opposed to using #pragma once) you could change that to:

(而不是使用#pragma一次)您可以将其更改为:

#ifndef __SOMEHEADER_H__#define __SOMEHEADER_H__// header contents#else #pragma message("Someheader.h superfluously included")#endif

And since the compiler outputs the name of the cpp file being compiled, that would let you know at least which cpp file is causing the header to be brought in multiple times.

并且由于编译器输出正在编译的cpp文件的名称,这将让您知道至少哪个cpp文件导致多次引入标头。

#11


PC-Lint can indeed do this. One easy way to do this is to configure it to detect just unused include files and ignore all other issues. This is pretty straightforward - to enable just message 766 ("Header file not used in module"), just include the options -w0 +e766 on the command line.

PC-Lint确实可以做到这一点。一种简单的方法是将其配置为仅检测未使用的包含文件并忽略所有其他问题。这非常简单 - 只启用消息766(“模块中未使用的头文件”),只需在命令行中包含选项-w0 + e766即可。

The same approach can also be used with related messages such as 964 ("Header file not directly used in module") and 966 ("Indirectly included header file not used in module").

相同的方法也可以与相关的消息一起使用,例如964(“未在模块中直接使用的头文件”)和966(“间接包含的未在模块中使用的头文件”)。

FWIW I wrote about this in more detail in a blog post last week at http://www.riverblade.co.uk/blog.php?archive=2008_09_01_archive.xml#3575027665614976318.

我上周在http://www.riverblade.co.uk/blog.php?archive=2008_09_01_archive.xml#3575027665614976318的一篇博文中更详细地写了这篇文章。

#12


If you are looking to remove unnecessary #include files in order to decrease build times, your time and money might be better spent parallelizing your build process using cl.exe /MP, make -j, Xoreax IncrediBuild, distcc/icecream, etc.

如果您希望删除不必要的#include文件以减少构建时间,那么使用cl.exe / MP,make -j,Xoreax IncrediBuild,distcc / icecream等可以更好地花时间和金钱来构建进程。

Of course, if you already have a parallel build process and you're still trying to speed it up, then by all means clean up your #include directives and remove those unnecessary dependencies.

当然,如果您已经有一个并行构建过程并且仍在尝试加速它,那么一定要清理#include指令并删除那些不必要的依赖项。

#13


Start with each include file, and ensure that each include file only includes what is necessary to compile itself. Any include files that are then missing for the C++ files, can be added to the C++ files themselves.

从每个包含文件开始,并确保每个包含文件仅包含编译自身所需的内容。然后,C ++文件中缺少的任何包含文件都可以添加到C ++文件本身。

For each include and source file, comment out each include file one at a time and see if it compiles.

对于每个包含文件和源文件,一次注释掉每个包含文件,看它是否编译。

It is also a good idea to sort the include files alphabetically, and where this is not possible, add a comment.

按字母顺序对包含文件进行排序也是一个好主意,如果不可能,请添加注释。

#14


Adding one or both of the following #defines will exclude often unnecessary header files and may substantially improvecompile times especially if the code that is not using Windows API functions.

添加以下一个或两个#defines将排除经常不必要的头文件,并且可能大大改善编译时间,尤其是在不使用Windows API函数的代码时。

#define WIN32_LEAN_AND_MEAN#define VC_EXTRALEAN

See http://support.microsoft.com/kb/166474

#15


If you aren't already, using a precompiled header to include everything that you're not going to change (platform headers, external SDK headers, or static already completed pieces of your project) will make a huge difference in build times.

如果您还没有,使用预编译的头文件包含您不会更改的所有内容(平台标头,外部SDK标头或项目的静态已完成部分)将在构建时间方面产生巨大差异。

http://msdn.microsoft.com/en-us/library/szfdksca(VS.71).aspx

Also, although it may be too late for your project, organizing your project into sections and not lumping all local headers to one big main header is a good practice, although it takes a little extra work.

此外,尽管对您的项目来说可能为时已晚,但将项目组织成各个部分而不是将所有本地标题集中到一个大的主标题是一个很好的做法,尽管需要一些额外的工作。

#16


If you would work with Eclipse CDT you could try out http://includator.com to optimize your include structure. However, Includator might not know enough about VC++'s predefined includes and setting up CDT to use VC++ with correct includes is not built into CDT yet.

如果您使用Eclipse CDT,可以尝试http://includator.com来优化您的包含结构。但是,Includator可能对VC ++的预定义包含知识不够,并且设置CDT以使用VC ++,而正确的包含还没有内置到CDT中。

#17


The latest Jetbrains IDE, CLion, automatically shows (in gray) the includes that are not used in the current file.

最新的Jetbrains IDE,CLion,自动显示(灰色)当前文件中未使用的包含。

It is also possible to have the list of all the unused includes (and also functions, methods, etc...) from the IDE.

也可以从IDE中获取所有未使用的包括(以及函数,方法等)的列表。

#18


Some of the existing answers state that it's hard. That's indeed true, because you need a full compiler to detect the cases in which a forward declaration would be appropriate. You cant parse C++ without knowing what the symbols mean; the grammar is simply too ambiguous for that. You must know whether a certain name names a class (could be forward-declared) or a variable (can't). Also, you need to be namespace-aware.

一些现有的答案表明它很难。这确实是事实,因为您需要一个完整的编译器来检测前向声明适合的情况。你无法解析C ++而不知道符号是什么意思;语法对此来说太模糊了。您必须知道某个名称是否命名一个类(可以是前向声明的)还是一个变量(不能)。此外,您需要知道名称空间。

#19


Maybe a little late, but I once found a WebKit perl script that did just what you wanted. It'll need some adapting I believe (I'm not well versed in perl), but it should do the trick:

也许有点晚了,但我曾经发现一个WebKit perl脚本可以完成你想要的。它需要一些适应我相信(我不熟悉perl),但它应该做的伎俩:

http://trac.webkit.org/browser/branches/old/safari-3-2-branch/WebKitTools/Scripts/find-extra-includes

(this is an old branch because trunk doesn't have the file anymore)

(这是一个旧分支,因为trunk不再有文件)

#20


If there's a particular header that you think isn't needed anymore (saystring.h), you can comment out that include then put this below all theincludes:

如果你认为不再需要一个特定的标题(saytring.h),你可以注释掉包含然后把它放在所有包含的下面:

#ifdef _STRING_H_#  error string.h is included indirectly#endif

Of course your interface headers might use a different #define conventionto record their inclusion in CPP memory. Or no convention, in which casethis approach won't work.

当然,您的接口标头可能使用不同的#define约定来记录它们包含在CPP内存中。或者没有惯例,在这种情况下,这种方法不起作用。

Then rebuild. There are three possibilities:

然后重建。有三种可能性:

  • It builds ok. string.h wasn't compile-critical, and the include for itcan be removed.

    它构建好了。 string.h不是编译关键的,可以删除它的include。

  • The #error trips. string.g was included indirectly somehowYou still don't know if string.h is required. If it is required, youshould directly #include it (see below).

    #error之旅。 string.g以某种方式间接包含在内你还不知道是否需要string.h。如果需要,你应直接#include它(见下文)。

  • You get some other compilation error. string.h was needed and isn't beingincluded indirectly, so the include was correct to begin with.

    你得到一些其他编译错误。 string.h是必需的,并不是间接包含的,所以包含是正确的开始。

Note that depending on indirect inclusion when your .h or .c directly usesanother .h is almost certainly a bug: you are in effect promising that yourcode will only require that header as long as some other header you're usingrequires it, which probably isn't what you meant.

请注意,当您的.h或.c直接使用其他.h时,取决于间接包含几乎肯定是一个错误:您实际上承诺,只要您正在使用的某个其他标头需要它,您的代码只需要该标头,这可能不是不是你的意思。

The caveats mentioned in other answers about headers that modify behaviorrather that declaring things which cause build failures apply here as well.

在其他答案中提到的关于修改行为的标题的警告也声明了导致构建失败的事情。

#1


While it won't reveal unneeded include files, Visual studio has a setting /showIncludes (right click on a .cpp file, Properties->C/C++->Advanced) that will output a tree of all included files at compile time. This can help in identifying files that shouldn't need to be included.

虽然它不会显示不需要的包含文件,但Visual Studio有一个设置/ showIncludes(右键单击.cpp文件,属性 - > C / C ++ - >高级),它将在编译时输出所有包含文件的树。这有助于识别不需要包含的文件。

You can also take a look at the pimpl idiom to let you get away with fewer header file dependencies to make it easier to see the cruft that you can remove.

您还可以查看pimpl习惯用法,以便减少头文件依赖性,从而更轻松地查看可以删除的内容。

#2


PC Lint works quite well for this, and it finds all sorts of other goofy problems for you too. It has command line options that can be used to create External Tools in Visual Studio, but I've found that the Visual Lint addin is easier to work with. Even the free version of Visual Lint helps. But give PC-Lint a shot. Configuring it so it doesn't give you too many warnings takes a bit of time, but you'll be amazed at what it turns up.

PC Lint对此非常有效,它也可以为您找到各种其他愚蠢的问题。它具有可用于在Visual Studio中创建外部工具的命令行选项,但我发现Visual Lint插件更易于使用。即使是免费版的Visual Lint也有帮助。但是给PC-Lint一个机会。配置它以便它不会给你太多的警告需要一点时间,但你会惊讶于它出现了什么。

#3


There's a new Clang-based tool, include-what-you-use, that aims to do this.

有一个新的基于Clang的工具,包括你使用的,旨在实现这一目标。

#4


!!DISCLAIMER!! I work on a commercial static analysis tool (not PC Lint). !!DISCLAIMER!!

!!免责声明!我从事商业静态分析工具(不是PC Lint)。 !!免责声明!

There are several issues with a simple non parsing approach:

简单的非解析方法有几个问题:

1) Overload Sets:

1)过载集:

It's possible that an overloaded function has declarations that come from different files. It might be that removing one header file results in a different overload being chosen rather than a compile error! The result will be a silent change in semantics that may be very difficult to track down afterwards.

重载函数可能具有来自不同文件的声明。可能是删除一个头文件会导致选择不同的重载而不是编译错误!结果将是语义的静默变化,之后可能很难跟踪。

2) Template specializations:

2)模板专业化:

Similar to the overload example, if you have partial or explicit specializations for a template you want them all to be visible when the template is used. It might be that specializations for the primary template are in different header files. Removing the header with the specialization will not cause a compile error, but may result in undefined behaviour if that specialization would have been selected. (See: Visibility of template specialization of C++ function)

与重载示例类似,如果您对模板有部分或显式特化,则希望在使用模板时它们都可见。可能是主模板的特化是在不同的头文件中。使用特化删除标头不会导致编译错误,但如果已选择该特化,则可能导致未定义的行为。 (参见:C ++函数模板特化的可见性)

As pointed out by 'msalters', performing a full analysis of the code also allows for analysis of class usage. By checking how a class is used though a specific path of files, it is possible that the definition of the class (and therefore all of its dependnecies) can be removed completely or at least moved to a level closer to the main source in the include tree.

正如'msalters'所指出的,对代码进行全面分析还可以分析类的使用情况。通过检查文件的特定路径如何使用类,有可能可以完全删除类的定义(以及它的所有依赖性),或者至少移动到更接近包含主要源的级别树。

#5


I don't know of any such tools, and I have thought about writing one in the past, but it turns out that this is a difficult problem to solve.

我不知道有任何这样的工具,我曾考虑过写一篇,但事实证明这是一个难以解决的问题。

Say your source file includes a.h and b.h; a.h contains #define USE_FEATURE_X and b.h uses #ifdef USE_FEATURE_X. If #include "a.h" is commented out, your file may still compile, but may not do what you expect. Detecting this programatically is non-trivial.

假设您的源文件包含a.h和b.h; a.h包含#define USE_FEATURE_X,b.h使用#ifdef USE_FEATURE_X。如果#include“a.h”被注释掉,您的文件仍然可以编译,但可能无法按预期执行。以编程方式检测这一点并非易事。

Whatever tool does this would need to know your build environment as well. If a.h looks like:

无论使用什么工具,您都需要了解构建环境。如果a.h看起来像:

#if defined( WINNT )   #define USE_FEATURE_X#endif

Then USE_FEATURE_X is only defined if WINNT is defined, so the tool would need to know what directives are generated by the compiler itself as well as which ones are specified in the compile command rather than in a header file.

然后仅在定义WINNT时定义USE_FEATURE_X,因此该工具需要知道编译器本身生成哪些指令以及在编译命令中而不是在头文件中指定哪些指令。

#6


Like Timmermans, I'm not familiar with any tools for this. But I have known programmers who wrote a Perl (or Python) script to try commenting out each include line one at a time and then compile each file.

像Timmermans一样,我对此并不熟悉任何工具。但我知道编写Perl(或Python)脚本的程序员尝试一次注释掉每个include行,然后编译每个文件。


It appears that now Eric Raymond has a tool for this.

看来现在Eric Raymond有了这个工具。

Google's cpplint.py has an "include what you use" rule (among many others), but as far as I can tell, no "include only what you use." Even so, it can be useful.

谷歌的cpplint.py有一个“包括你使用的”规则(以及其他许多规则),但据我所知,没有“仅包括你使用的内容”。即便如此,它也很有用。

#7


If you're interested in this topic in general, you might want to check out Lakos' Large Scale C++ Software Design. It's a bit dated, but goes into lots of "physical design" issues like finding the absolute minimum of headers that need to be included. I haven't really seen this sort of thing discussed anywhere else.

如果您对这个主题感兴趣,可能需要查看Lakos的大规模C ++软件设计。这有点过时了,但是会遇到很多“物理设计”问题,例如找到需要包含的标题的绝对最小值。我还没有真正看到其他任何地方讨论过这种事情。

#8


Give Include Manager a try. It integrates easily in Visual Studio and visualizes your include paths which helps you to find unnecessary stuff.Internally it uses Graphviz but there are many more cool features. And although it is a commercial product it has a very low price.

试试Include Manager。它可以在Visual Studio中轻松集成,并可视化您的包含路径,帮助您找到不必要的东西。内部它使用Graphviz但有更多很酷的功能。虽然它是商业产品,但价格非常低廉。

#9


You can build an include graph using C/C++ Include File Dependencies Watcher, and find unneeded includes visually.

您可以使用C / C ++ Include File Dependencies Watcher构建包含图,并直观地查找不需要的包含。

#10


If your header files generally start with

如果您的头文件通常以

#ifndef __SOMEHEADER_H__#define __SOMEHEADER_H__// header contents#endif

(as opposed to using #pragma once) you could change that to:

(而不是使用#pragma一次)您可以将其更改为:

#ifndef __SOMEHEADER_H__#define __SOMEHEADER_H__// header contents#else #pragma message("Someheader.h superfluously included")#endif

And since the compiler outputs the name of the cpp file being compiled, that would let you know at least which cpp file is causing the header to be brought in multiple times.

并且由于编译器输出正在编译的cpp文件的名称,这将让您知道至少哪个cpp文件导致多次引入标头。

#11


PC-Lint can indeed do this. One easy way to do this is to configure it to detect just unused include files and ignore all other issues. This is pretty straightforward - to enable just message 766 ("Header file not used in module"), just include the options -w0 +e766 on the command line.

PC-Lint确实可以做到这一点。一种简单的方法是将其配置为仅检测未使用的包含文件并忽略所有其他问题。这非常简单 - 只启用消息766(“模块中未使用的头文件”),只需在命令行中包含选项-w0 + e766即可。

The same approach can also be used with related messages such as 964 ("Header file not directly used in module") and 966 ("Indirectly included header file not used in module").

相同的方法也可以与相关的消息一起使用,例如964(“未在模块中直接使用的头文件”)和966(“间接包含的未在模块中使用的头文件”)。

FWIW I wrote about this in more detail in a blog post last week at http://www.riverblade.co.uk/blog.php?archive=2008_09_01_archive.xml#3575027665614976318.

我上周在http://www.riverblade.co.uk/blog.php?archive=2008_09_01_archive.xml#3575027665614976318的一篇博文中更详细地写了这篇文章。

#12


If you are looking to remove unnecessary #include files in order to decrease build times, your time and money might be better spent parallelizing your build process using cl.exe /MP, make -j, Xoreax IncrediBuild, distcc/icecream, etc.

如果您希望删除不必要的#include文件以减少构建时间,那么使用cl.exe / MP,make -j,Xoreax IncrediBuild,distcc / icecream等可以更好地花时间和金钱来构建进程。

Of course, if you already have a parallel build process and you're still trying to speed it up, then by all means clean up your #include directives and remove those unnecessary dependencies.

当然,如果您已经有一个并行构建过程并且仍在尝试加速它,那么一定要清理#include指令并删除那些不必要的依赖项。

#13


Start with each include file, and ensure that each include file only includes what is necessary to compile itself. Any include files that are then missing for the C++ files, can be added to the C++ files themselves.

从每个包含文件开始,并确保每个包含文件仅包含编译自身所需的内容。然后,C ++文件中缺少的任何包含文件都可以添加到C ++文件本身。

For each include and source file, comment out each include file one at a time and see if it compiles.

对于每个包含文件和源文件,一次注释掉每个包含文件,看它是否编译。

It is also a good idea to sort the include files alphabetically, and where this is not possible, add a comment.

按字母顺序对包含文件进行排序也是一个好主意,如果不可能,请添加注释。

#14


Adding one or both of the following #defines will exclude often unnecessary header files and may substantially improvecompile times especially if the code that is not using Windows API functions.

添加以下一个或两个#defines将排除经常不必要的头文件,并且可能大大改善编译时间,尤其是在不使用Windows API函数的代码时。

#define WIN32_LEAN_AND_MEAN#define VC_EXTRALEAN

See http://support.microsoft.com/kb/166474

#15


If you aren't already, using a precompiled header to include everything that you're not going to change (platform headers, external SDK headers, or static already completed pieces of your project) will make a huge difference in build times.

如果您还没有,使用预编译的头文件包含您不会更改的所有内容(平台标头,外部SDK标头或项目的静态已完成部分)将在构建时间方面产生巨大差异。

http://msdn.microsoft.com/en-us/library/szfdksca(VS.71).aspx

Also, although it may be too late for your project, organizing your project into sections and not lumping all local headers to one big main header is a good practice, although it takes a little extra work.

此外,尽管对您的项目来说可能为时已晚,但将项目组织成各个部分而不是将所有本地标题集中到一个大的主标题是一个很好的做法,尽管需要一些额外的工作。

#16


If you would work with Eclipse CDT you could try out http://includator.com to optimize your include structure. However, Includator might not know enough about VC++'s predefined includes and setting up CDT to use VC++ with correct includes is not built into CDT yet.

如果您使用Eclipse CDT,可以尝试http://includator.com来优化您的包含结构。但是,Includator可能对VC ++的预定义包含知识不够,并且设置CDT以使用VC ++,而正确的包含还没有内置到CDT中。

#17


The latest Jetbrains IDE, CLion, automatically shows (in gray) the includes that are not used in the current file.

最新的Jetbrains IDE,CLion,自动显示(灰色)当前文件中未使用的包含。

It is also possible to have the list of all the unused includes (and also functions, methods, etc...) from the IDE.

也可以从IDE中获取所有未使用的包括(以及函数,方法等)的列表。

#18


Some of the existing answers state that it's hard. That's indeed true, because you need a full compiler to detect the cases in which a forward declaration would be appropriate. You cant parse C++ without knowing what the symbols mean; the grammar is simply too ambiguous for that. You must know whether a certain name names a class (could be forward-declared) or a variable (can't). Also, you need to be namespace-aware.

一些现有的答案表明它很难。这确实是事实,因为您需要一个完整的编译器来检测前向声明适合的情况。你无法解析C ++而不知道符号是什么意思;语法对此来说太模糊了。您必须知道某个名称是否命名一个类(可以是前向声明的)还是一个变量(不能)。此外,您需要知道名称空间。

#19


Maybe a little late, but I once found a WebKit perl script that did just what you wanted. It'll need some adapting I believe (I'm not well versed in perl), but it should do the trick:

也许有点晚了,但我曾经发现一个WebKit perl脚本可以完成你想要的。它需要一些适应我相信(我不熟悉perl),但它应该做的伎俩:

http://trac.webkit.org/browser/branches/old/safari-3-2-branch/WebKitTools/Scripts/find-extra-includes

(this is an old branch because trunk doesn't have the file anymore)

(这是一个旧分支,因为trunk不再有文件)

#20


If there's a particular header that you think isn't needed anymore (saystring.h), you can comment out that include then put this below all theincludes:

如果你认为不再需要一个特定的标题(saytring.h),你可以注释掉包含然后把它放在所有包含的下面:

#ifdef _STRING_H_#  error string.h is included indirectly#endif

Of course your interface headers might use a different #define conventionto record their inclusion in CPP memory. Or no convention, in which casethis approach won't work.

当然,您的接口标头可能使用不同的#define约定来记录它们包含在CPP内存中。或者没有惯例,在这种情况下,这种方法不起作用。

Then rebuild. There are three possibilities:

然后重建。有三种可能性:

  • It builds ok. string.h wasn't compile-critical, and the include for itcan be removed.

    它构建好了。 string.h不是编译关键的,可以删除它的include。

  • The #error trips. string.g was included indirectly somehowYou still don't know if string.h is required. If it is required, youshould directly #include it (see below).

    #error之旅。 string.g以某种方式间接包含在内你还不知道是否需要string.h。如果需要,你应直接#include它(见下文)。

  • You get some other compilation error. string.h was needed and isn't beingincluded indirectly, so the include was correct to begin with.

    你得到一些其他编译错误。 string.h是必需的,并不是间接包含的,所以包含是正确的开始。

Note that depending on indirect inclusion when your .h or .c directly usesanother .h is almost certainly a bug: you are in effect promising that yourcode will only require that header as long as some other header you're usingrequires it, which probably isn't what you meant.

请注意,当您的.h或.c直接使用其他.h时,取决于间接包含几乎肯定是一个错误:您实际上承诺,只要您正在使用的某个其他标头需要它,您的代码只需要该标头,这可能不是不是你的意思。

The caveats mentioned in other answers about headers that modify behaviorrather that declaring things which cause build failures apply here as well.

在其他答案中提到的关于修改行为的标题的警告也声明了导致构建失败的事情。