📘 C++ 范围 for
循环详解(Range-based for loop)
一、什么是范围 for
循环?
范围 for
循环(Range-based for loop) 是 C++11 引入的一种简化容器/数组遍历的方式。它通过自动调用容器的 begin()
和 end()
方法,实现对每个元素的遍历,无需手动管理索引或迭代器 。
二、语法格式
cpp
复制代码
for (declaration : expression) {
// 循环体
}
declaration
:用于声明当前遍历的元素(可使用 auto
自动推导类型)
expression
:表示要遍历的容器或数组
三、基本原理
✅ 自动调用 begin()
和 end()
范围 for
循环会自动调用容器的 begin()
和 end()
方法,获取起始和结束迭代器,然后依次遍历每个元素。
示例说明:
cpp
复制代码
std::vector<int> numbers = {1, 2, 3, 4, 5};
for (int num : numbers) {
std::cout << num << " ";
}
✅ 等价于传统写法:
cpp
复制代码
std::vector<int> numbers = {1, 2, 3, 4, 5};
for (auto it = numbers.begin(); it != numbers.end(); ++it) {
int num = *it;
std::cout << num << " ";
}
四、适用对象
范围 for
循环适用于以下对象:
类型
是否支持
示例
数组
✅ 支持
int arr[] = {1, 2, 3};
标准库容器
✅ 支持
std::vector
, std::list
, std::map
自定义容器类
✅ 支持
需要实现 begin()
和 end()
方法
字符串(std::string
)
✅ 支持
逐字符遍历
原始指针容器
❌ 不支持
没有 begin()
/end()
方法
五、优点
优点
说明
代码简洁
避免手动写 begin()
/end()
安全性高
不易越界,适合只读遍历
可读性强
更贴近自然语言,易于理解
自动类型推导
可使用 auto
自动识别元素类型
六、局限性
局限
说明
不能直接访问索引
无法通过循环变量获取当前索引
不能反向遍历
只能从前往后遍历
不能跳过元素
无法控制步长(如 i += 2
)
不能修改容器结构
不能在循环中添加/删除元素
七、代码示例
1. 遍历数组
cpp
复制代码
int arr[] = {1, 2, 3, 4, 5};
for (int num : arr) {
std::cout << num << " ";
}
// 输出: 1 2 3 4 5
2. 遍历 std::vector
cpp
复制代码
#include <iostream>
#include <vector>
int main() {
std::vector<int> nums = {10, 20, 30, 40, 50};
for (auto num : nums) {
std::cout << num << " ";
}
// 输出: 10 20 30 40 50
return 0;
}
3. 遍历 std::map
cpp
复制代码
#include <iostream>
#include <map>
int main() {
std::map<std::string, int> scores = {
{"Alice", 95},
{"Bob", 80},
{"Charlie", 88}
};
for (const auto &pair : scores) {
std::cout << pair.first << ": " << pair.second << std::endl;
}
return 0;
}
输出:
复制代码
Alice: 95
Bob: 80
Charlie: 88
4. 遍历 std::string
cpp
复制代码
#include <iostream>
#include <string>
int main() {
std::string str = "Hello";
for (char c : str) {
std::cout << c << " ";
}
// 输出: H e l l o
return 0;
}
5. 使用引用修改元素
cpp
复制代码
#include <iostream>
#include <vector>
int main() {
std::vector<int> nums = {1, 2, 3, 4, 5};
for (auto &num : nums) {
num *= 2; // 修改原容器中的值
}
for (auto num : nums) {
std::cout << num << " ";
}
// 输出: 2 4 6 8 10
return 0;
}
6. 使用 auto
自动推导类型
cpp
复制代码
#include <iostream>
#include <vector>
int main() {
std::vector<std::string> names = {"Tom", "Jerry", "Spike"};
for (const auto &name : names) {
std::cout << name << std::endl;
}
return 0;
}
八、常见错误与修正
错误写法
正确写法
说明
for (int x : 10)
for (int x : vector)
范围 for
必须作用于容器
for (int x : {});
std::vector<int> v = {1, 2}; for (int x : v)
空列表不能单独使用
for (int &x : const std::vector<int> v)
for (int x : v)
不能通过引用修改常量容器
for (int x : arr, arr + 5)
for (int x : arr)
不需要手动指定范围,自动识别容器边界
九、性能与安全建议
建议
说明
使用 const auto &
遍历只读容器
避免拷贝,提高性能
使用 auto &
修改容器元素
通过引用直接操作原数据
避免在循环中修改容器结构
如 push_back()
、erase()
,可能导致迭代器失效
优先使用 const
如果不打算修改元素,使用 const auto &
提高代码清晰度
十、通俗类比
你可以把范围 for
循环理解为:
cpp
复制代码
for (auto &item : shopping_list) {
std::cout << "Buy: " << item << std::endl;
}
shopping_list
是你要遍历的容器
item
是当前遍历到的元素
循环自动帮你"取出"每一个物品,不需要你手动操作索引或指针
十一、术语对照表
英文术语
中文解释
Range-based for loop
范围 for
循环
Container
容器(如 vector
, map
)
Iterator
迭代器(传统 for
循环中使用)
Reference
引用(&
表示)
auto
自动类型推导
const auto &
常量引用,防止拷贝和修改原始数据
十二、设计建议
场景
推荐写法
只读遍历容器
for (const auto &item : container)
修改容器元素
for (auto &item : container)
遍历字符串
for (char c : str)
遍历 map 的键值对
for (const auto &pair : my_map)
避免拷贝
使用引用 &
避免修改容器结构
不在循环中调用 push_back()
、erase()
等方法
十三、总结
特性
说明
语法简洁
for (auto &item : container)
自动调用 begin()
/ end()
无需手动写迭代器
适用于容器和数组
vector
, map
, array
, string
等
不能控制索引
无法获取当前索引值
不适合动态修改容器
如增删元素会导致迭代器失效