std::filesystem::absolute() 基于当前工作目录解析相对路径,对绝对路径直接返回,不消除“../”或“./”,需配合 canonical() 或 weakly_canonical() 才能规范化;它不检查存在性或符号链接,而 canonical() 会解析链接并验证可达性,失败则抛异常。

用 std::filesystem::absolute() 获取绝对路径,但要注意当前工作目录
调用 std::filesystem::absolute() 会基于当前工作目录(CWD)解析路径。如果传入的是相对路径(比如 "data/config.txt"),它会拼上 CWD 得到完整路径;如果传入的已经是绝对路径(如 "/home/user/file" 或 "C:\temp\log.txt"),它直接返回原路径,不作修改。
常见错误是假设 absolute() 总能“规范化”路径——它不会消除 "../" 或冗余 "./",例如 absolute("foo/../bar") 返回的是 /current/working/dir/foo/../bar,不是 /current/working/dir/bar。需要进一步调用 std::filesystem::canonical() 或 std::filesystem::weakly_canonical() 才能折叠。
- 确保编译器支持 C++17 且启用了
-std=c++17(Clang/GCC)或/std:c++17(MSVC) - 链接时无需额外库(GCC/Clang 默认支持,MSVC 需启用
/MD或/MT,但不需额外 link) - 若目标路径不存在,
absolute()仍能构造路径,但canonical()会抛std::filesystem::filesystem_error
用 std::filesystem::relative() 计算两个路径间的相对路径
std::filesystem::relative(path, base) 返回从 base 到 path 的相对路径。它要求两个路径都存在(或至少 base 存在),否则行为未定义(实际中多数实现会抛异常)。它的逻辑是先将两者转为绝对路径,再计算公共前缀,最后用 ".." 回溯 + 剩余部分拼接。
典型误用:把字符串字面量直接当 base 传,却没确认该目录真实存在。比如 relative("/tmp/a.txt", "/tmp") 返回 "a.txt",但 relative("/tmp/a.txt", "/home") 返回 "../tmp/a.txt"。
- 若
path和base无公共祖先(如 Windows 下跨盘符、Linux 下挂载点隔离),relative()可能返回空或抛异常 - 结果不含末尾斜杠,即使
path是目录;如需目录语义,手动加"/" - Windows 下注意大小写:NTFS 默认不区分,但路径比较时
relative()按字节逐个匹配,"C:/Foo"和"c:/foo"可能无法正确对齐
获取当前可执行文件所在目录的绝对路径(跨平台可靠做法)
很多人想“让程序知道自己在哪”,但 std::filesystem::current_path() 返回的是进程当前工作目录,不等于可执行文件位置。真正可靠的方案依赖平台 API:
- Linux/macOS:用
readlink("/proc/self/exe", buf, sizeof(buf)-1)(Linux)或_NSGetExecutablePath()(macOS),再用absolute()归一化 - Windows:用
GetModuleFileNameA(NULL, buf, sizeof(buf)),然后传给std::filesystem::path - 封装时建议统一返回
std::filesystem::path,后续所有操作都基于它,避免字符串拼接引入斜杠错误
别试图用 argv[0] 解析——它可能是相对路径、软链接名,甚至被篡改过。
相对路径转绝对路径时容易忽略的权限和符号链接问题
调用 absolute() 不检查文件是否存在,也不解析符号链接;而 canonical() 会解析所有符号链接并验证路径可达性,失败则抛异常。这意味着:
- 若路径含符号链接且目标不可达(如权限不足、挂载点失效),
canonical()失败,但absolute()成功 - 某些 CI 环境或容器中,
/proc/self/exe不可用,此时 fallback 到argv[0]并配合weakly_canonical()更稳妥 - Windows 上长路径(>260 字符)需启用 manifest 或调用
SetCurrentDirectoryW()配合 Unicode API,否则absolute()可能截断
最常被跳过的一步:没检查 std::filesystem::exists() 就直接 canonical(),导致程序崩溃而非优雅报错。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!











