在 Visual Studio 中(笔者版本 Visual Studio 2017),新生成的C++项目文件的的头文件夹下会默认有头文件stdafx.h,而源文件夹下则默认有源文件stdafx.cpp,手动将这些文件删除后,编译时系统还会报错。下面记录笔者了解到的关于头文件stdafx.h的信息。

使用预编译头

  stdafx.h并不是标准C++头文件,也就是说,该文件本质上相当于自定义的一个头文件( 这里是VS默认自定义的文件),与项目的源代码文件存放在同一个文件文件夹下,通过#include"stdafx.h"引用;

  从内容上来说,头文件stdafx.h中可以包含

  1.标准系统包含文件

  2.经常使用的但不常更改的特定于项目的包含文件

  标准系统包含文件 : 即常用的与C标准库对应的头文件,如标准输入头文件stdio.h、字符串头文件string.h等文件。

  自定义的包含文件 : 即用户根据项目需要自定义的头文件。

  在使用头文件 stdafx.h 时,将所有源程序中所需的包含文件( .h 文件 )都包含在头文件stdafx.h中,具体的做法就是将原本各个文件中所需要的类似于#include<stdio.h>的头文件包含语句都存放在头文件stdfax.h中,之后各个单独的文件中不需要再对存在于stdafx.h中的头文件进行单独声明,而只需要包含有头文件stdafx.h即可。

    #include"stdafx.h"  //通过该语句包含头文件stdafx.h,该语句需放在每个源文件文件的开头,否则会报错

  同时,stdafx.h也可以存放内容改动较少的自定义的头文件。

  相应的,源文件stdafx.cpp中内容仅包含以下语句

  #include "stdafx.h" //事实上,stdfax.cpp只用于编译头文件stdafx.h中包含的所有内容

  事实上,stdafx.cpp只用于编译头文件stdafx.h中包含的所有内容。

开启/关闭预编译头

  选中目标项目,右键 -> 属性 -> C/C++ -> 预编译头,在右侧的选项中可以修改预编译头的相关设置。

  1.可以修改选项为使用/不使用预编译头,从而开启/关闭预编译头机制;

  2.可以修改预编译头文件的名字(预编译头是一种机制,具体的头文件名是可以自行指定的);

  3.修改预编译头输出文件的路径;

  实际上,每个单独的源文件中均存在关于预编译头的属性,用于指定不同的编译策略,可供使用者自行选择。特别的,源文件stdafx.cpp的预编译头属性栏应设置为 创建(/Yc),这样设置表示预编译头是由该源文件生成,而被其他文件使用。

  

预编译头的原理

  在标准头文件中,往往包含有大量的函数声明、宏定义等方面的内容。一方面,原始预处理过程会将实际头文件的内容复制到源程序中,这给编译过程增加很大的开销;另一方面,多个不同的单独的源文件可能会重复声明头文件的包含关系来满足传统的函数声明的要求,这也给编译器带来了重复劳动。另外,当文件发生修改时,整个文件需要重新编译,而作为文件中内容不会更改的头文件的内容也需要重新编译,造成不必要的开销。为了降低在编译过程中诸如此类不必要的开销,引入了预编译头的机制。

  在编译过程中,stdafx.cpp和stdafx.h文件用于生成一个预编译头文件 project.pch和预编译类型文件stdafx.obj。

  如前面提到的,stdafx.cpp存放的是#include "stdafx.h"。在第一次编译过程中,stdafx.cpp首先被编译处理,将头文件stdafx.h中包含的所有的头文件进行预编译,从而生成一个预编译头文件project.pch,在之后的编译过程中,只要stdafx.h没有被修改(时间戳没有发生改变),则编译器可以直接使用预编译头文件project.pch的内容,而不需要重新编译stdafx.h。之后的每个包含有stdafx.h头文件的独立文件编译过程都会使用该pch文件中的内容,即一次集中编译头文件后,之后可重复使用。

  实际上,生成预编译头文件同样是耗时的,但是在后续的修改编译过程中,只要没有修改stdafx.h和stdafx.cpp文件的内容,就不需要重新生成预编译头文件,也就避免了许多头文件处理的过程,从而大大减少了传统重复处理头文件的开销。相应的,由于预编译头文件包含有众多头文件的处理信息,故而其本身会占用较大的存储空间,故而可以注意清理不需要的预编译头。

  一般来说,将被项目中多个独立文件引用的标准头文件和特定项目中一般不做修改的头文件放在stdafx.h中可以大大提升程序编译时的效率

关于报错

  在使用预编译头机制时,可能会遇到一些问题

  1. 无法打开预编译头文件"xxx.pch":no such file or directory 的问题

  分析:根据上面的原理解释,可能是由于编译器无法通过stdafx.cpp创建一个预编译文件,从而其他文件没有办法去引用该pch文件。

  解决方案:选中源文件stdafx.cpp,右键 -> 属性 -> C/C++ -> 预编译头,出现上述问题一般是由于预编译头的选项从 创建 变为了 使用 ,通过将选项重新改为创建可解决问题。

  2. 在查找预编译头文件时遇到意外的文件结尾

  需要将指令#include"stdafx.h" 放在每个文件的开始位置,以供处理。

  参考:

  Microsoft文档:Precompiled header file

  百度知道:C++ 中stdafx.h是什么意思

  stackoverflow:问题的第一个答案

Visual Studio中头文件stdafx.h的作用的更多相关文章

  1. 预编译头文件 StdAfx.h

    预编译头文件: 最常见的使用场景就是 StdAfx.h 文件,在这个文件中包含常用的头文件,比如windows.h,cstdio,string,别的 .cpp 文件去包含 StdAfx.h 头文件.编 ...

  2. C++ 中头文件(.h)和源文件(.cc)的写法简述

    用C++编写比较大型的项目时,文件的分割管理确实确实是非常必要的 .下面就非常简洁明了地谈谈头文件(.h)和源文件(.cc)应该怎么写. 头文件(.h):写类的声明(包括类里面的成员和方法的声明).函 ...

  3. C++预编译头文件 – stdafx.h

    预编译头文件的由来 也许请教了别的高手之后,他们会告诉你,这是预编译头,必须包含.可是,这到底是为什么呢?预编译头有什么用呢? 咱们从头文件的编译原理讲起.其实头文件并不神秘,其在编译时的作用,就是把 ...

  4. Visual Studio中xml文件使用app.config、web.config等的智能提示的方法

    在.Net开发的过程中,有时我们需要使用Xml文件作为配置文件(基于某些情况的考虑),而不是app.config.web.config这种,但是我们在xml中配置时希望可以增加类似编辑app.conf ...

  5. C++中头文件与源文件的作用详解

    一.C++ 编译模式 通常,在一个 C++ 程序中,只包含两类文件―― .cpp 文件和 .h 文件.其中,.cpp 文件被称作 C++ 源文件,里面放的都是 C++ 的源代码:而 .h 文件则被称作 ...

  6. C++中头文件(.h)和源文件(.cpp)都应该写些什么

    头文件(.h): 写类的声明(包括类里面的成员和方法的声明).函数原型.#define常数等,但一般来说不写出具体的实现. 在写头文件时需要注意,在开头和结尾处必须按照如下样式加上预编译语句(如下): ...

  7. 在一个非默认的位置包含头文件stdafx.h

    如果stdafx.h和你当前的工程不在一个文件夹下,当你在代码中第一行写下#include "stdafx.h"时,VC编译器会根据编译规则(相关的规则请查看MSDN)来区别std ...

  8. C语言中头文件<stdio.h>中的#ifndef _STDIO_H_

    先了解这里的相关知识:http://www.cnblogs.com/stemon/p/4000468.html 头文件的中的#ifndef,这是一个很关键的东西.比如你有两个C文件,这两个C文件都in ...

  9. visual studio中csproj文件中的project guid改为小写

    安装了vs2019之后,发现有的项目中引用的其他项目的源码,但是无法识别了. 最后发现是因为project guid是大写导致的. https://stackoverflow.com/question ...

随机推荐

  1. 入门系列之在Ubuntu上使用MySQL设置远程数据库优化站点性能

    欢迎大家前往腾讯云+社区,获取更多腾讯海量技术实践干货哦~ 本文由苏子晨 发表于云+社区专栏 介绍 随着您的应用程序或网站的增长,您可能已经超出了当前的服务器设置.如果您在同一台计算机上托管Web服务 ...

  2. Bash编程(6) String操作

    1. 拼接 1) 简单的字符串拼接如:PATH=$PATH:$HOME/bin.如果拼接的字符串包含空格或特殊字符,需要使用双引号括起,如: var=$HOME/bin # 注释并不是赋值的一部分 v ...

  3. JavaScript使用Object.defineProperty方法实现双数据绑定

    Object.defineProperty这个方法非常值得学习,很多mvc框架中的双向数据绑定就是通过它来实现的. 本着互联网分享精神,今天我就将我自己的见解分享给大家,希望能有所帮助. 开始使用 O ...

  4. hexo+github搭建博客跳坑

    hexo+GitHub搭建博客过程中,hexo安装成功,可以启动和运行,但是访问localhost:4000却无法访问,弄了半天,最后发现是福昕阅读器占用了4000端口 解决办法: 采用命令hexo ...

  5. [转]what’s the difference between @Component ,@Repository & @Service annotations in Spring

    原文地址:https://www.cnblogs.com/softidea/p/6070314.html @Component is equivalent to <bean> @Servi ...

  6. 2017年11月26日 C#流&&窗体对话框

    C#流 在顶端加入using System.IO就可以使用流 StreamReder a = new StreamReder();//读取 前面什么都可以 = sr.ReadToEnd();//用法 ...

  7. 互联网轻量级框架SSM-查缺补漏第五天

    简言:这个地方我就草草过了,NBA圣诞大战,偷偷看比赛,真香~ 第五章映射器 5.2select元素 自动映射和驼峰映射:MyBatis提供了自动映射功能,在默认的情况下自动映射功能是开启的. 在se ...

  8. FLASK实现上传下载功能

    #!-*-coding=utf-8-*- # from flask import Flask # # app = Flask(__name__) # # # @app.route('/') # def ...

  9. javaScript 面向对象开发实例

    javaScript 面向对象开发实例 这个是结合require的模块化开发,首先创建构造函数: //test.js 1 function Test(lists) { var config={ nam ...

  10. react+antd 选项卡切换

    index.js: import React from 'react'; import ReactDOM from 'react-dom'; import CardSecond from './Car ...