应使用可执行文件所在目录而非当前工作目录拼接路径,因current_path()随启动方式变化不可靠;需通过平台API获取可执行路径后用std::filesystem::path拼接并canonical()规范化。

用 std::filesystem::current_path() 获取当前工作目录再拼接是否可靠
不推荐直接拼接字符串。因为 std::filesystem::current_path() 返回的是运行时的工作目录(不是可执行文件所在目录),且不同启动方式下值完全不同——比如从 IDE 启动、终端 cd 到某目录后运行、或通过 systemd 启动,current_path() 结果可能天差地别。
常见错误现象:std::filesystem::current_path() / "data/config.json" 在 IDE 里能读到文件,打包发布后就报 std::filesystem::filesystem_error: No such file or directory。
- 始终用
std::filesystem::path的/操作符拼接,别用+或string::append() - 若目标是“程序同级目录下的文件”,得先获取可执行路径,再用
parent_path() - Windows 下路径分隔符自动处理,但手动拼接
"\\"或"/"容易出错;Linux 下大小写敏感,拼错大小写也会失败
如何真正拿到可执行文件所在目录(而非 current_path)
标准库没直接提供该功能,得靠平台 API + std::filesystem::path 封装。C++20 不支持 executable_path(),必须自己取。
Windows 下用 GetModuleFileNameW(),Linux/macOS 下用 readlink("/proc/self/exe", ...) 或 _NSGetExecutablePath()。封装后统一转成 std::filesystem::path 才安全。
立即学习“C++免费学习笔记(深入)”;
- Linux 示例:
readlink("/proc/self/exe", buf, sizeof(buf)-1)返回的是符号链接路径,需调用std::filesystem::canonical()解析真实路径 - Windows 示例:用
GetModuleFileNameW()得到宽字符路径,必须用std::filesystem::path构造函数接收wchar_t*,不能先转 UTF-8 字符串再构造 - 别忘了加异常处理:
try { ... } catch (const std::filesystem::filesystem_error& e) { /* 处理路径无效 */ }
std::filesystem::path::append() 和 / 操作符的区别
两者都用于拼接路径,但语义和行为不同:append() 是“追加路径组件”,会把参数当作相对路径段处理;而 / 操作符更直观,也更常用。
错误用法:p.append("../config") —— 这会让路径变成 ./../config,实际效果取决于当前 p 是否以 / 结尾,极易误判。
- 优先用
p / "subdir" / "file.txt",清晰、链式、不易错 -
append()适合动态构建:比如循环中逐段添加for (const auto& seg : segments) p.append(seg); -
append()不接受绝对路径字符串(如"/etc/passwd"),会抛filesystem_error;/操作符遇到绝对右操作数会忽略左操作数(即直接替换)
跨平台绝对路径拼接的最小可靠模式
没有“一劳永逸”的单行方案。可靠做法是:先确定基准目录(可执行目录 or 用户指定目录),再用 std::filesystem::path 拼接,最后用 std::filesystem::absolute() 或 std::filesystem::canonical() 规范化。
注意:absolute() 只补前缀,不解析 ..;canonical() 才真正归一化并检查存在性(可能抛异常)。
- 推荐初始化模式:
auto base = get_executable_dir(); auto cfg_path = base / "etc" / "app.conf"; - 读取前务必检查:
if (!std::filesystem::exists(cfg_path)) { /* 提示用户或 fallback */ } - 避免在日志或配置中硬写
"./data"——.是 relative,依赖 current_path,上线即崩
最麻烦的点其实是“谁来负责路径合法性校验”:是构造时立刻 canonical(),还是等 open 文件时由系统报错?前者提前暴露问题,后者更轻量但错误位置滞后。选哪个,得看你的错误容忍边界在哪。



















