使用预编译头提高编译速度
使用预编译头提高编译速度
什么是预编译头
在介绍预编译头之前,有必要了解一下C/C++的编译方式。C/C++的编译单元是源文件(带有.c、.cc、.cpp等扩展名的文件),在编译一个源文件之前,预处理器会把这个源文件中所有通过#include指令包含进来的头文件递归地展开,也就是把所有直接或间接包含的头文件原封不动地插入进来。当这个过程结束之后,才开始编译。
正如之前所说,这些头文件内容很多,那么复制头文件内容所花时间就很大了。而采用设置预编译头的方法编译时间就会大幅缩小,这是因为编译器会先编译prh.cpp,生成一个.pch文件,之后编译其他.cpp文件就会直接使用.pch中的内容,这样就避免了大量的复制,从而大幅缩短编译时间。
为了解决这个问题,预编译头应运而生。顾名思义,预编译头就是预先把头文件编译好,在编译源文件的时候直接取用这些编译结果,避免对头文件重复编译。这项技术能大幅提高C++的编译速度。
Visual C++生成的扩展名为.pch的文件即是预编译头生成的结果。
如何使用预编译头
介绍一下如何启用预编译头,以下操作是在Visual Studio 2017上进行的。
首先要做的,是在项目中添加一个头文件以及源文件,这两个文件是给预编译头这个机制使用的。它们的名称并没有限制,这里把它们命名为pch.h (precompiled_header.h)和pch.cpp(precompiled_header.cpp)(Visual C++使用的默认名字是StdAfx.h和StdAfx.cpp)。
precompiled.h将被指定成预编译头文件,所有在这个头文件中的代码都会被预编译。可以把任意代码添加到这个文件,一般的做法是把常用的头文件包含进来,例如:
1 2 3 4 5 6 7 8 9 10 11 |
#pragma once #include <Windows.h> #include <algorithm> #include <cstdint> #include <functional> #include <list> #include <map> #include <set> #include <string> #include <vector> |
pch.cpp则为pch.h提供了编译的载体,因为C/C++只能对源文件编译,而不能对头文件编译。pch.cpp只需要包含pch.h即可(由于示例项目的需要,包含语句中包含了相对路径):
1 |
#include "pch.h" |
接下来,指定通过pch.cpp来生成预编译结果。在“解决方案资源管理器中”,右击pch.cpp文件,在弹出的菜单中点击“属性”,打开该文件的属性页窗口。
在属性页窗口中,打开“预编译头”配置页,设置“预编译头”选项的值为“创建(/Yc)”,设置“预编译头文件”选项的值为“pch.h”。如下图所示:
点击确定完成设置。如此一来,在编译pch.cpp的时候就会生成预编译结果,也就是.pch文件。
设置了生成预编译结果之后,还需要设置使用预编译结果。右击项目project,打开项目的属性页窗口中打开“预编译头”配置页,设置“预编译头”选项的值为“使用(/Yu)”,设置“预编译头文件”选项的值为“pch.h”。
最后,需要在所有的源文件中包含预编译头文件,并且该文件必须是第一个包含的。这是使用预编译头的硬性规定,假如不遵守这个规定,编译会失败。重复地在所有源文件中添加预编译头文件很繁琐,所幸的是Visual C++提供了强制在所有源文件中包含指定头文件的选项。同样在项目的属性页窗口中,打开“C/C++”分类下的“高级”配置页,在“强制包含文件”的选项中,添加“pch.h”即可,如下图所示:
至此,预编译头的设置就完成了。注意,在预编译头文件之后再重复包含该文件内已包含的头文件并不会有问题,所以不必特意去掉那些重复的包含语句。