为何std::filesystem::absolute在Windows下会解析.和..,但在POSIX平台不会?
嘿,这个问题我之前踩过同款坑,其实说穿了就是C++标准的宽松定义+不同平台底层API的行为差异搞的鬼~
首先得拎清楚:C++17标准对std::filesystem::absolute的要求真的很基础——只要返回的是绝对路径就行,并没有强制要求必须解析掉.(当前目录)、..(父目录)这类“冗余”组件。所以不同编译器的实现自然就跟着各自平台的系统API走了。
就说Windows这边,MSVC的std::filesystem::absolute是基于Win32的GetFullPathNameW接口做的,而这个系统API本身就会自动帮你把.和..给解析掉,相当于顺带做了路径规范化的工作,所以你拿到的结果就是已经“清理干净”的绝对路径。
再看Linux这类POSIX平台,GCC/libstdc++的实现就不一样了。它的absolute函数其实只是把相对路径和当前工作目录简单拼接到一起,并没有调用专门的规范化API(比如POSIX的realpath)。毕竟标准没要求它做这个额外工作,所以它就只完成了“绝对化”最核心的任务,.和..自然就原封不动保留下来了。
要是你想在所有平台都拿到解析过.和..的干净绝对路径,别死磕absolute,换std::filesystem::canonical或者std::filesystem::weakly_canonical就行——这俩函数的本职工作就是路径规范化,不管Windows还是Linux,都会把这些冗余组件处理得明明白白。
举个你提到的例子:当前目录是/home/user(Linux)或者C:\Users(Windows),调用absolute("foo/./bar/../baz"):
- Windows下会直接返回
C:\Users\foo\baz - Linux下则会返回
/home/user/foo/./bar/../baz
但如果换成canonical,两边都会返回干净的最终路径。
备注:内容来源于stack exchange,提问作者Atul Rawat




