range-based for循环要求容器支持begin()/end()且返回前向迭代器,适用于vector、list、map、array及原生数组;最简形式为for(const auto& item : container);遍历map时item为pair,C++17起推荐用结构化绑定for(const auto& [key, value] : my_map)。

range-based for 循环的基本写法与适用容器
只要容器支持 begin() 和 end() 成员函数(或非成员重载),且返回的迭代器满足前向迭代器要求,就能用范围 for。标准容器如 std::vector、std::list、std::map、std::array 和原生数组都符合。
最简形式是:
for (const auto& item : container) { /* 使用 item */ }注意这里用 const auto& 是为了不拷贝、不修改——这是最常用也最安全的起点。
- 想修改元素?用
auto&(非常量左值引用) - 需要拷贝一份再处理?用
auto(值语义) - 遍历
std::map时,item是std::pair类型,不是单个值
遍历 map 时取 key 和 value 的正确方式
直接写 for (auto& p : my_map) 后,p.first 是 key,p.second 是 value。别试图用结构化绑定以外的方式“拆开”——C++17 起推荐用结构化绑定更清晰:
for (const auto& [key, value] : my_map) {
std::cout << key << " -> " << value << "\n";
}注意:[key, value] 是声明,不是访问语法;类型自动推导;如果要修改 value,得把 const auto& 换成 auto&,但 key 仍不可改(因为是 const Key)。
立即学习“C++免费学习笔记(深入)”;
- 用
auto(无引用)会触发std::pair拷贝,对大对象不划算 -
std::unordered_map同样适用该写法,顺序不保证而已 - 若编译器不支持 C++17,退回用
p.first/p.second
常见错误:试图在循环中修改容器大小
范围 for 底层依赖 begin()/end() 迭代器。一旦在循环体中调用 push_back()、erase() 等改变容器 size 或 layout 的操作,原有迭代器很可能失效,导致未定义行为——不是崩溃就是跳过元素。
-
std::vector在push_back()触发 reallocation 时,所有迭代器立即失效 -
std::map插入一般不使其他迭代器失效,但erase(it)会使it失效,而范围 for 的内部迭代器正是这个it - 真要边遍历边删?用传统 for +
erase()返回值,或先收集待删 key 再批量处理
自定义类型如何支持 range-based for
只需提供 begin() 和 end() 成员函数(或自由函数),返回可解引用、可递增、可比较相等的迭代器类型即可。例如:
class MyRange {
int data[3] = {1, 2, 3};
public:
int* begin() { return data; }
int* end() { return data + 3; }
};然后就能写 for (int x : MyRange{}) { ... }。注意:返回裸指针也合法,只要满足迭代器概念;但生产代码建议封装为类迭代器,支持 const 版本和反向遍历。
容易被忽略的是 const 容器的支持——必须额外提供 const_begin()/const_end() 或重载 const 成员函数,否则 const MyRange r; 无法参与范围 for。











