C++ include头文件的顺序以及双引号““和尖括号<>的区别
本文章进一步详细解释 #include 的头文件包含机制,包括搜索路径的处理、双引号 "" 和尖括号 <> 在不同环境中的使用差异,以及它们的底层机制。
1. 头文件包含机制和搜索路径详解
#include 是一个预处理指令,用于在编译前将指定的头文件的内容插入到当前源文件中。在 C++ 编译过程中,头文件的查找顺序和搜索路径的选择会影响项目的编译成功与否。
双引号 "" 的搜索路径机制
当使用双引号 #include "filename" 包含头文件时,编译器通常按照以下顺序查找头文件:
- 当前文件所在的目录:
- 编译器首先查找与当前源文件同目录的头文件。这是因为我们通常使用双引号来包含本地定义的头文件(如类定义的
.h文件)。
- 编译器首先查找与当前源文件同目录的头文件。这是因为我们通常使用双引号来包含本地定义的头文件(如类定义的
- 包含该文件的文件夹:
- 如果该源文件本身是通过
#include被其他文件引用的,编译器会在最先引用该文件的文件夹内查找。
- 如果该源文件本身是通过
- 指定的项目包含路径(通过编译器参数指定的路径,例如
-I选项):- 编译器会查找通过编译器命令行参数指定的头文件路径(
-I/path/to/include)。这个路径可以是多个目录,依赖于构建系统的设置。
- 编译器会查找通过编译器命令行参数指定的头文件路径(
- 全局系统路径:
- 如果前面的路径中没有找到文件,编译器会在全局头文件目录中查找。通常这些路径是操作系统或者 IDE 预先配置好的系统路径,比如
/usr/include(Linux 系统)或者C:\Program Files\(Windows 系统)。
- 如果前面的路径中没有找到文件,编译器会在全局头文件目录中查找。通常这些路径是操作系统或者 IDE 预先配置好的系统路径,比如
尖括号 <> 的搜索路径机制
当使用尖括号 #include <filename> 包含头文件时,编译器仅在全局或系统路径中查找头文件,忽略当前目录。这是为了更高效地查找标准库和第三方库中的头文件。查找路径如下:
-
标准库路径:
- 编译器首先在 C++ 标准库的路径中查找头文件。这些路径可能包含
<iostream>,<vector>,<string>等标准库文件。
- 编译器首先在 C++ 标准库的路径中查找头文件。这些路径可能包含
-
系统库路径:
- 然后,编译器会查找系统头文件路径。比如,在 Linux 系统中,常见路径为
/usr/include和/usr/local/include,而在 Windows 系统中,可能是C:\Program Files (x86)\Microsoft Visual Studio\。
- 然后,编译器会查找系统头文件路径。比如,在 Linux 系统中,常见路径为
-
指定的头文件路径:
- 依赖于编译器设置,可能还会根据用户指定的第三方库路径(如通过
-I指定的路径)来查找第三方库的头文件,例如 Boost、Qt 等。
- 依赖于编译器设置,可能还会根据用户指定的第三方库路径(如通过
双引号和尖括号的选择与差异
- 使用双引号
""更适合引用 项目内部 或者 本地定义的头文件,因为它会首先查找当前文件目录,确保本地头文件的优先级较高。这种方式适用于项目间的模块化开发。 - 使用尖括号
<>通常用于 标准库 和 外部库 的头文件,避免在当前目录下无意中引用到同名的头文件。
更详细的搜索过程比较
| 使用符号 | 查找顺序 | 适用场景 |
|---|---|---|
双引号 "" | 1. 当前目录 2. 引用文件所在目录 3. 编译器指定的项目路径(如 -I)4. 系统路径 | 用于引用本地的头文件 |
尖括号 <> | 1. 标准库路径 2. 系统路径 3. 第三方路径 | 用于标准库和外部库的头文件 |
编译器选项与头文件路径
在使用编译器时,可以通过选项配置头文件的查找路径。例如:
-
GCC/Clang:
-I:指定额外的头文件路径。例如,g++ -I/path/to/headers main.cpp会告诉编译器在/path/to/headers中查找头文件。
-
Visual Studio:
- 在项目属性的 "C/C++" > "附加包含目录" 中,可以指定额外的包含目录。编译器会在这些目录中查找双引号
""和尖括号<>所包含的头文件。
- 在项目属性的 "C/C++" > "附加包含目录" 中,可以指定额外的包含目录。编译器会在这些目录中查找双引号
-
CMake:
- 使用
include_directories()或target_include_directories()指定头文件的搜索路径。
- 使用
2. 双引号和尖括号的深层机制
双引号和尖括号的主要区别在于它们告诉编译器如何查找文件的路径。尖括号中的头文件往往是一些不常修改的外部依赖,比如标准库文件、系统级文件或者第三方库,而双引号中的头文件是用户自定义的文件,更容易发生变化。因此,双引号和尖括号的查找路径和优先级设计不同。
双引号 vs 尖括号查找行为
双引号 "filename":
1. 查找当前目录/源文件目录
2. 查找编译器路径(通过 -I 指定)
3. 查找标准系统路径
尖括号 <filename>:
1. 查找标准系统路径
2. 查找第三方路径
3. #include 的例子与实践
包含自定义头文件的实例
#include "MyClass.h" // 当前目录查找
#include "subfolder/Helper.h" // 指定子文件夹查找
#include <iostream> // 系统库查找,标准C++库
#include <cmath> // 系统路径下的数学库
在这个例子中,"MyClass.h" 和 "subfolder/Helper.h" 都是项目内的文件,编译器会从源文件所在的目录或项目结构中的路径查找。<iostream> 和 <cmath> 是标准库的头文件,因此编译器直接在标准路径中查找。
4. 如何正确组织头文件
为了避免潜在的查找冲突和提高编译速度,建议遵循以下头文件组织原则:
-
使用前向声明:
- 尽量在头文件中使用前向声明来减少包含不必要的头文件。例如,在类成员中引用其他类的指针时,可以通过前向声明避免引入整个类的定义。
class MyClass; // 前向声明
class AnotherClass {
MyClass* ptr; // 使用指针或引用即可避免包含整个 MyClass 头文件
};
2.防止多次包含(Include Guard):
- 为了避免头文件的多次包含,常用的做法是使用包含防护,即
#ifndef、#define、#endif组合,或者在现代 C++ 中使用#pragma once。 -
// MyClass.h
#ifndef MYCLASS_H
#define MYCLASS_Hclass MyClass {
// Class Definition
};#endif // MYCLASS_H
-
确保头文件独立:
- 每个头文件应该可以独立包含,不依赖其他头文件的顺序。通过包含防护和适当的前向声明,避免头文件之间的复杂依赖关系。
5. 总结
- 双引号
"":优先用于包含项目中的本地文件,编译器会先从当前目录查找,再到系统路径查找。 - 尖括号
<>:用于包含标准库或外部库文件,编译器直接从系统路径查找。 - 头文件包含顺序:优先包含与当前实现文件相关的头文件,然后是标准库头文件,接着是第三方库,最后是项目内部其他模块的头文件。
相关文章:
C++ include头文件的顺序以及双引号““和尖括号<>的区别
本文章进一步详细解释 #include 的头文件包含机制,包括搜索路径的处理、双引号 "" 和尖括号 <> 在不同环境中的使用差异,以及它们的底层机制。 1. 头文件包含机制和搜索路径详解 #include 是一个预处理指令,用于在编译前将…...
Flutter鸿蒙版本灵活使用方法间的回调处理复杂化的逻辑
目录 写在前面 示例代码 main.dart: one.dart: 代码解析 1. 主入口 main 函数 2. MyApp 类 3. CallbackExample 类 4. onok 函数 5. one 函数 写在后面 写在前面 在 Flutter 开发中,灵活使用函数之间的回调带来了多种好处,包括提高可重用性、…...
视频号直播自动回复与循环发送话术-自动化插件
我们在做视频号直播的时候,会有这种自动回复咨询问题的功能 唯一客服浏览器插件现在就支持,在视频号直播后台,自动化回复用户问题,以及循环发送我们的介绍话术...
springcloud之服务集群注册与发现 Eureka
前言 1:对于能提供完整领域服务接口功能的RPC而言,例如;gRPC、Thrift、Dubbo等,服务的注册与发现都是核心功能中非常重要的一环,使得微服务得到统一管理。 2:在分布式领域中有个著名的CAP理论;…...
C++:模拟实现list
目录 节点 迭代器 整体框架 构造函数 empty_init 拷贝构造 赋值重载 析构函数 clear insert erase push_back和push_front pop_back和push_front size empty Print_Container 节点 对于链表节点,我们需要一个数据、一个前驱指针、一个后继指针来维护…...
解锁5 大无水印热门短视频素材库
想让你的抖音视频更出彩吗?想知道那些爆款视频的素材源头吗?快来了解以下 5 个超棒的视频素材下载平台。 蛙学网 国内的视频素材佼佼者,有大量 4K 高清且无水印的素材,自然风光、情感生活等类别任你选,不少还免费&…...
【电商购物管理系统】Python+Django网页界面平台+商品管理+数据库
一、介绍 电商购物管理系统,本系统前端使用HTML、CSS、BootStrap等技术搭建前端界面,后端使用Django框架处理用户的逻辑请求。主要功能有: 管理员登录与管理:管理员可以登录后台,对用户和商品进行增删改查的操作。用…...
AD9248驱动的简易示波器设计——FPGA学习笔记21
一、原理 我们这里设计的是显示 1024 个波形数据点, 在绘制每一行的图像的时候, 比对每一个数据和 VS 的 Y 坐标是否相等, 如果相等就绘制这个波形点。 这样我们就能完成 1024 个波形点在整个屏幕的显示。 二、乒乓操作 可见FPGA实现双口RAM…...
微软十月补丁星期二发现了 118 个漏洞
微软将在2024 年 10 月补丁星期二解决 118 个漏洞,并且有证据表明发布的 5 个漏洞被野蛮利用和/或公开披露,尽管微软尚未将其中任何一个漏洞评定为严重漏洞。 在这五个漏洞中,微软列出了两个已被利用的漏洞,这两个漏洞现在都已列…...
到底是微服务,还是SOA?
引言:大概正式工作有5年了,换了三个大厂【也是真特么世道艰难,中国互联网人才饱和了】。基本上每个公司有的架构都不太相同,干过TOC和TOB的业务,但是大家用的架构都不太相同。有坚持ALL in one的SB,最后服务…...
JDK17常用新特性
目前国内大部分开发人员都是在使用jdk8,甚至是jdk6,但是随着jdk的更新迭代,jdk8我觉得可能就会慢慢的淡出舞台,随着目前主流框架最新版推出明确说明了不再支持jdk8,也促使我不得不抓紧学习了解一波jdk17的新特性&#…...
【分布式微服务云原生】探索负载均衡的艺术:深入理解与实践指南
探索负载均衡的艺术:深入理解与实践指南 摘要: 在本文中,我们将深入探讨负载均衡的概念、重要性以及实现负载均衡的多种算法。通过详细的技术解析、Java代码示例、流程图和对比表格,您将了解如何选择合适的负载均衡策略来优化资源…...
拥抱云原生
专题七:云原生实战72课时 专题简介: 云原生正在改变世界,新一代架构思想ServiceMesh、Serverless改变传统软件架构模式,本专题基于完全云上架构实战,结合微服务架构和云计算平台两者的优势,属于架构师必备…...
关于使用若依并快速构建系统的操作指南
准备阶段--下载源码(脚手架) 1.1 若依官网地址:https://www.ruoyi.vip/ 1.2 选择“前后端分离版本进行下载”,如下图所示 1.3 跳转gitee后,直接按如下步骤进行下载。 前后端模块分离 解压,并打开到项目…...
【分布式微服务云原生】 选择SOAP还是RESTful API?深入探讨与实践指南
🌐 选择SOAP还是RESTful API?深入探讨与实践指南 摘要: 在构建现代Web服务时,开发者常常面临一个关键决策:是选择SOAP还是RESTful API?本文将为您提供一个全面的比较,包括两者的适用场景、安全…...
HarmonyOS NEXT 应用开发实战(五、页面的生命周期及使用介绍)
HarmonyOS NEXT是华为推出的最新操作系统,arkUI是其提供的用户界面框架。arkUI的页面生命周期管理对于开发者来说非常重要,因为它涉及到页面的创建、显示、隐藏、销毁等各个阶段。以下是arkUI页面生命周期的介绍及使用举例。 页面的生命周期的作用 页面…...
C# 比较两个集合和比较对象
1、比较集合 /// <summary> /// 比较两个集合 /// </summary> /// <typeparam name"T"></typeparam> /// <param name"list1"></param> /// <param name"list2"></param> /// <returns>&…...
Spark高级用法-自定义函数
用户可以根据需求自己封装计算的逻辑,对字段数据进行计算 内置函数,是spark提供的对字段操作的方法 ,split(字段) 对字段中的数进行切割,F.sum(字段) 会将该字段下的数据进行求和 实际业务中又能内置函数不满足计算需求࿰…...
『Mysql进阶』Mysql explain详解(五)
目录 Explain 介绍 Explain分析示例 explain中的列 1. id 列 2. select_type 列 3. table 列 4. partitions 列 5. type 列 6. possible_keys 列 7. key 列 8. key_len 列 9. ref 列 10. rows 列 11. filtered 列 12. Extra 列 Explain 介绍 EXPLAIN 语句提供有…...
【工具】音视频翻译工具基于Whisper+ChatGPT
OpenAI推出的开源语音识别工具Whisper,以其卓越的语音识别能力,在音频和视频文件处理领域大放异彩。与此同时,ChatGPT也在翻译领域崭露头角,其强大的翻译能力备受赞誉。因此,一些字幕制作团队敏锐地捕捉到了这两者的结…...
手把手教你搞定CMT2300A的315MHz匹配电路:从原理图到物料清单(附实测数据)
深入解析CMT2300A在315MHz频段的射频匹配电路设计与实战优化 作为一名长期深耕射频硬件设计的工程师,我最近在工业遥控器项目中遇到了一个典型挑战:如何为CMT2300A设计稳定可靠的315MHz匹配电路。与常见的433MHz应用不同,315MHz频段在元件参数…...
Qwen1.5-0.5B-Chat电商应用:商品咨询机器人搭建教程
Qwen1.5-0.5B-Chat电商应用:商品咨询机器人搭建教程 1. 引言:为什么需要一个轻量级商品咨询机器人? 想象一下,你经营着一家网店,每天有成百上千的顾客涌入。他们的问题五花八门:“这件衣服有L码吗&#x…...
人体关键点检测实战:如何用OKS和AP评估模型性能(附Python代码示例)
人体关键点检测实战:OKS与AP指标深度解析与Python实现 在计算机视觉领域,人体姿态估计一直是热门研究方向,而准确评估模型性能则是项目落地的关键环节。不同于常规的目标检测任务,人体关键点检测需要更精细的评估体系——这正是OK…...
3D打印模型优化实战:从问题诊断到高效输出的完整指南
3D打印模型优化实战:从问题诊断到高效输出的完整指南 【免费下载链接】BlenderUSDZ Simple USDZ file exporter plugin for Blender3D 项目地址: https://gitcode.com/gh_mirrors/bl/BlenderUSDZ 1. 痛点定位:3D打印模型导出的四大核心障碍 诊断…...
5个高效实用的英雄联盟工具集使用指南
5个高效实用的英雄联盟工具集使用指南 【免费下载链接】League-Toolkit 兴趣使然的、简单易用的英雄联盟工具集。支持战绩查询、自动秒选等功能。基于 LCU API。 项目地址: https://gitcode.com/gh_mirrors/le/League-Toolkit League-Toolkit是一款基于LCU API开发的开源…...
新手友好:通过快马用自然语言生成你的第一个openclaw卸载脚本
作为一个刚接触编程的新手,想要自己动手写一个软件卸载脚本确实会有点无从下手。最近我在学习Python时,发现用InsCode(快马)平台可以很轻松地通过自然语言描述生成完整代码,特别适合我们这样的初学者。下面我就分享一下如何用这个平台快速创建…...
零基础玩转Llama-3.2-3B:Ollama部署+实战问答全流程
零基础玩转Llama-3.2-3B:Ollama部署实战问答全流程 1. 模型介绍与准备 1.1 Llama-3.2-3B模型概述 Llama-3.2-3B是Meta公司开发的多语言大型语言模型(LLM),属于Llama 3.2系列中的3B参数版本。这个纯文本模型经过指令微调优化&am…...
拒了一个只要1.8万的45岁大佬
因公众号更改推送规则,请点“在看”并加“星标”第一时间获取精彩技术分享点击关注#互联网架构师公众号,领取架构师全套资料 都在这里0、2T架构师学习资料干货分上一篇:2T架构师学习资料干货分享大家好,我是互联网架构师ÿ…...
Python多进程+ZeroMQ+内存映射=真无锁?资深架构师用17个生产事故告诉你为什么92%的“去GIL”方案在高并发下静默失败
第一章:Python无锁GIL环境下的并发模型避坑指南Python 的全局解释器锁(GIL)长期被误认为是“无锁”环境,实则恰恰相反——GIL 是 CPython 解释器中一把严格的互斥锁,它确保任意时刻仅有一个线程执行 Python 字节码。所…...
Qwen3.5-9B+OpenClaw组合方案:3类高性价比自动化场景实测
Qwen3.5-9BOpenClaw组合方案:3类高性价比自动化场景实测 1. 为什么选择这个组合? 去年夏天,我花了整整两周时间在本地部署各种开源大模型,试图找到一个既能在预算内运行、又能稳定执行自动化任务的方案。经过反复测试࿰…...
