std::filesystem::recursive_directory_iterator 是 c++17 标准库提供的深度优先目录遍历迭代器,自动按 dfs 顺序遍历子目录及其中文件,无需手动实现递归或栈管理,使用前需确保路径合法、权限足够并链接 -lstdc++fs(gcc/clang)。

std::filesystem::recursive_directory_iterator 是什么
它不是“自己实现”的遍历器,而是 C++17 标准库 std::filesystem 提供的现成工具,用于深度优先遍历目录树。你不需要手写递归逻辑或维护栈——recursive_directory_iterator 内部已按 DFS 顺序(先子目录、再子目录内文件)自动推进。
怎么用 recursive_directory_iterator 做 DFS 遍历
核心是构造迭代器后用范围 for 遍历,它默认就是深度优先;若需显式控制,可用 increment() 和 decrement(),但绝大多数场景直接 for 循环即可。
常见错误现象:std::filesystem::recursive_directory_iterator 构造时抛出 std::filesystem::filesystem_error(如路径不存在、无权限),不加 try-catch 会导致程序崩溃。
- 确保编译器支持 C++17(GCC 8+、Clang 7+、MSVC 2017 15.7+),并开启
-std=c++17 - 链接
stdc++fs(GCC/Clang 下需显式加-lstdc++fs;MSVC 不需要) - 路径必须是合法目录,否则构造即失败;可用
std::filesystem::is_directory()预检 - 遍历时跳过符号链接(默认行为),如需跟随,构造时传入
std::filesystem::directory_options::follow_directory_symlink
#include <filesystem>
#include <iostream>
namespace fs = std::filesystem;
int main() {
try {
for (const auto& entry : fs::recursive_directory_iterator("/tmp/test")) {
std::cout
<h3>为什么它不是广度优先(BFS)</h3>
<p><code>recursive_directory_iterator</code> 的遍历顺序由底层实现保证为 DFS:进入一个目录后,立即递归其第一个子项,直到叶子;回溯后再处理同级下一个。这与 BFS(逐层展开)有本质区别。</p><div class="aritcle_card flexRow artxards">
<div class="artcardd flexRow">
<a class="aritcle_card_img" rel="nofollow" href="/xiazai/skill2659" title="C++"><img
src="https://img.php.cn/upload/skill/000/000/081/178927213426672.jpg" alt="C++" onerror="this.onerror='';this.src='/static/lhimages/moren/morentu.png'" ></a>
<div class="aritcle_card_info flexColumn">
<a rel="nofollow" href="/xiazai/skill2659" title="C++" class="overflowclass">C++</a>
<p class="overflowclass">"空空如也"</p>
</div>
<a rel="nofollow" href="/xiazai/skill2659" title="C++" class="aritcle_card_btn flexRow flexcenter"><b></b><span>下载</span>
</a>
</div>
</div>
<p>性能影响:DFS 内存占用低(仅需栈深 ≈ 最大嵌套层数),适合深层窄树;BFS 则需缓存整层路径,内存随宽度线性增长。标准库没提供 BFS 迭代器,真要 BFS 得自己用 <code>std::queue</code> + <code>directory_iterator</code> 实现。</p>
<ul>
<li>无法通过参数切换成 BFS —— 没有对应选项</li>
<li>调用 <code>pop()</code> 或 <code>disable_recursion_pending()</code> 可临时跳过当前目录的递归,但不改变整体 DFS 本质</li>
<li>若需跳过特定子目录(如 <code>.git</code>),应在循环中检查 <code>entry.is_directory()</code> 和 <code>entry.path().filename()</code> 后 continue</li>
</ul>
<h3>容易被忽略的细节和坑</h3>
<p>最常被漏掉的是异常安全和符号链接行为。很多人只写 for 循环,却没意识到:权限不足的子目录会直接终止整个遍历(而非跳过);符号链接默认不进入,但某些项目恰恰依赖跟随链接访问真实路径。</p>
<ul>
<li>
<code>recursive_directory_iterator</code> 默认不抛出 I/O 错误(如读取失败的子目录),而是跳过并继续 —— 除非你调用 <code>increment()</code> 显式推进并捕获异常</li>
<li>Windows 上路径分隔符用反斜杠,但 <code>std::filesystem::path</code> 内部统一处理,建议始终用正斜杠或 <code>fs::path("a") / "b"</code> 拼接</li>
<li>遍历过程中修改目录结构(如删除正在访问的子目录)是未定义行为,实际可能 crash 或跳过条目</li>
<li>移动拷贝语义:迭代器可移动但不可拷贝;若需多处使用,应重新构造或缓存 <code>path()</code> 字符串</li>
</ul>
<p>真正复杂的点在于错误恢复策略——标准迭代器不提供“跳过当前失败目录并继续”的内置机制,你得靠 try/catch 包裹单次 increment,再手动推进,这会让代码迅速变重。别低估这个细节的实操成本。</p></iostream></filesystem>C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!










