标准库和第三方库头文件必须用尖括号<>,自定义头文件必须用双引号"";因查找路径不同,混用会导致编译失败或引入错误版本。

标准库和第三方库头文件必须用尖括号 <>,自定义头文件必须用双引号 "" —— 混用可能编译失败或引入错误版本。
为什么 #include <vector> 不能写成 #include "vector"
编译器对 <> 和 "" 的查找路径完全不同:<> 直接跳过当前目录,只查系统路径(如 /usr/include/c++/13/);而 "vector" 会先在当前源文件所在目录找,再退回到系统路径。如果项目目录下恰好有个叫 vector 的文件(比如测试用的 mock 头),"vector" 就会误加载它,导致符号重复、模板实例化失败等隐蔽错误。
- Linux/macOS 下,
<vector>对应的是编译器自带的标准库实现路径,"vector"可能匹配到你项目根目录下的vector文件(哪怕只是个空文件) - Windows 上 MSVC 同样遵循该规则,且 Visual Studio 的 Intellisense 有时会“假装”支持
"vector",但实际构建时仍可能失败 - Clang/GCC 在严格模式(
-Wsystem-headers或启用-pedantic)下会对"vector"发出警告
为什么 #include "utils.h" 不该写成 #include <utils.h>
<utils.h> 完全跳过当前项目目录,只查系统路径 —— 所以除非你把 utils.h 手动装进 /usr/include(不推荐),否则必然报错 fatal error: utils.h: No such file or directory。
- 即使你加了
-I./include,<utils.h>也不会去./include查,它只认系统级路径(除非你用-isystem,但那是给系统头用的,会禁用警告) - 某些 IDE(如 VS Code + CMake Tools)可能缓存了旧路径,看起来“能跳转”,但终端里
make或cmake --build仍会失败 - 团队协作时,别人没配同样的
-I路径,<utils.h>就彻底不可用
大型项目中路径写法的实际约束
像 Google C++ Style Guide 或 Chromium 的规范明确要求:自定义头文件使用带子目录的 "" 形式(如 "base/logging.h"),且构建系统需通过 -I 把项目根或 src/ 加入搜索路径,而不是写 "../base/logging.h"。
立即学习“C++免费学习笔记(深入)”;
-
"../base/logging.h"看似直观,但一旦文件移动位置或构建工作目录变化,路径就断掉 -
"base/logging.h"是稳定的逻辑路径,依赖-Isrc实现映射,和源码树结构一致 - CMake 中用
target_include_directories(mylib PRIVATE ${CMAKE_SOURCE_DIR}/src)才能让"base/logging.h"正确解析
容易被忽略的细节:预处理阶段就决定路径,和运行时无关
头文件包含发生在编译前的预处理阶段,路径解析完全由编译器完成,和 LD_LIBRARY_PATH、RPATH、动态链接库路径毫无关系。这意味着:
- 改环境变量不影响
#include查找结果 - 用
g++ -E可直接看到预处理后展开的完整路径,验证是否加载了预期文件 - 头文件里再嵌套
#include,也遵守相同规则 —— 所以"utils.h"里写#include <iostream>是对的,但写#include "iostream"就危险


















