不必要的包含文件是否有开销?

时间:2015-05-05 20:18:24

标签: c++ c++11 compilation code-organization

我已经看到了一些关于如何在C ++项目中检测不必要的#include文件的问题。这个问题经常引起我的兴趣,但我从来没有找到满意的答案。

如果包含一些头文件,这些头文件没有在c ++项目中使用,那是一个开销吗?我理解这意味着在编译之前,所有头文件的内容都将被复制到包含的源文件中,这将导致大量不必要的编译。

这种开销在多长时间内传播到编译对象文件和二进制文件?

  

Aren的编译器能够做一些优化以确保这一点   一种开销不会转移到生成的目标文件和   二进制文件?

考虑到事实,我可能对编译器优化一无所知,我仍然想问这个,以防有答案。

  

作为一名程序员,他使用各种各样的c ++库来完成他的工作,   我应该遵循什么样的编程实践来不断避免   这样的开销?让自己与每个人都非常熟悉   图书馆的唯一出路是什么?

4 个答案:

答案 0 :(得分:23)

对于几乎所有标头,它不会影响二进制文件的性能甚至二进制文件的内容。 声明根本不生成代码,内联/静态/匿名命名空间定义如果不使用则会被优化掉,并且没有标题应该包含外部可见的定义(如果包含标题则会中断由不止一个翻译单位)。

As @ T.C。指出,异常是具有非平凡构造函数的内部可见静态对象。例如,iostream就是这样做的。该程序的行为必须像调用构造函数一样,并且编译器通常没有足够的信息来优化构造函数。

但是,它会影响编译所需的时间以及更改标头时将重新编译的文件数。对于大型项目,这足以激励人们关注不必要的包含。

答案 1 :(得分:4)

除了明显更长的编译时间外,还可能存在其他问题。最重要的一个是IMHO对外部库的依赖。您不希望您的程序依赖于更多的库,然后是必要的。

然后,您还需要在要为程序构建的每个系统中安装这些库。这可能会成为一场噩梦,尤其是当下一个程序员需要安装一些数据库客户端库时,尽管程序从不使用数据库。

此外,特别是库标题通常倾向于定义宏。有时这些宏具有非常通用的名称,这些名称会破坏您的代码,或者与您可能实际需要的其他库头不兼容。

答案 2 :(得分:3)

当然,任何#include都是开销。编译器需要解析该文件。

所以要避免它们。尽可能使用前向声明。

它将加快编译速度。请参阅Scott Myers关于该主题的书籍

答案 3 :(得分:1)

简单的答案是YES,就编译而言,它是一个开销,但对于运行时,它只会产生任何差异。原因是假设您添加#include <iostream>仅作为示例)并假设您没有使用其任何功能,那么g ++ 4.5.2还有一些额外的18,560行代码要处理(< EM>汇编)。但就运行时开销而言,我几乎认为它不会产生性能问题。

您也可以参考Are unused includes harmful in C/C++?我非常喜欢David Young提出的这个观点

  

在标题中声明为外部并在a中定义的任何单例   源文件将包含在您的程序中。这明显增加了   内存使用率可能会导致性能开销   导致一个人更频繁地访问他们的页面文件(不是很多   现在的问题是,因为单身人士通常是中小型的   因为我认识的大多数人都有6 GB以上的RAM。