#ifndef中的#include包装——有任何价值吗?

4

我继承了一个 C/C++ 代码库,在许多 .cpp 文件中,#include 指令被包裹在 #ifndef 中,并且使用内部单个 include 头文件的 #define

例如:

#ifndef _INC_WINDOWS
#include <windows.h>
#endif

而windows.h看起来像

#ifndef _INC_WINDOWS
#define _INC_WINDOWS
...header file stuff....
#endif // _INC_WINDOWS

我认为这样做是为了加速代码的编译/预处理过程。

我认为这样做既难看又为时过早的优化,但由于项目从清洁状态开始需要5分钟的构建时间,我不想让事情变得更糟。

那么这种做法是否增加了任何价值或大大加快了速度呢?是否可以整理它们?

更新:编译器为MSVC(VS2005),平台为Win32 / WinCE。

2个回答

10
值得注意的是,一些实现有#pragma once和/或头文件包含保护检测优化,在这两种情况下,预处理器会自动跳过它以前包含过的头文件的打开、读取或处理。
因此,在那些编译器上,例如MSVC和GCC,这种“优化”是无意义的,应该由头文件负责处理多次包含。但是,在#include非常低效的编译器上,这可能是一种优化。如果代码路径具有病态可移植性,并且<windows.h>不是指众所周知的Win32头文件,而是指同名的某个用户定义的头文件呢?
头文件也可能没有多重包含保护,这种检查实际上是必要的。在这种情况下,我建议更改头文件。头文件的整个目的是作为复制粘贴代码的替代品:不应该花费三行来包括一个头文件。
编辑:
既然你说你只关心MSVC,我会做一个批量编辑,计时构建,只是为了确保之前的程序员不知道我不知道的事情。如果有帮助,可以添加#pragma once。如果所有这些都真的减缓了速度,请使用预编译头文件。
或者忽略它,但不要为新文件或添加到旧文件的新#include使用保护。
根据我是否有更重要的事情需要担心,这是一个经典的周五下午工作,我不会在上面花费潜在的生产时间。

1
编译器是MSVC,平台是Win32/WinCE。听起来像是重构的投票结果。 - Simeon Pilgrim

2

如果一个文件被包含进来,那么整个文件都需要被读取,甚至打开/关闭文件的开销可能是非常大的。通过在 include 声明周围加上防护指令,就不必打开它了。像这样的问题,正确的答案总是:尝试去掉 ifndef/endif 防护指令,然后使用秒表测试一下...


那么这就是我的问题的核心,有没有别人测试过这个在现代代码库和现代工具集上导致的差异? - Simeon Pilgrim
1
我知道有一个C++代码库,在这个过程中可以减少几分钟的构建时间(总构建时间为两个小时)。但是打开预编译头文件会产生更大的影响。而且,“现代”的概念在这里可能没有任何有用的意义!每个C++项目的构建系统可能略有不同,几乎所有的构建系统都基于古老的概念。没有“现代”的开发系统会让用户进行这种活动。 - Daniel Earwicker
“现代”这个观点很好。我真正的意思是不要讲述那些十年前在Pentium 3 PC上运行VS6的故事。 - Simeon Pilgrim

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接