范围 for 循环是 C++11 引入的语法特性,用于简化遍历容器或数组元素的过程。它比传统 for 循环更简洁安全,特别适合初学者。以下是详细讲解:
基本语法
for (元素类型 变量名 : 容器/数组) {// 循环体(使用变量名访问当前元素)
}
或使用 auto
自动推断类型:
for (auto 变量名 : 容器/数组) {// 循环体
}
与普通 for 循环对比
传统遍历向量的方式:
for (vector<int>::iterator it = v.begin(); it != v.end(); ++it)
{// 使用 *it 访问元素
}
范围 for 循环更简洁,可读性更强,且不易出错(如避免了迭代器越界等问题)。
关键特点
- 自动遍历:无需手动控制索引或迭代器
- 边界安全:自动处理开始和结束位置,避免越界
- 简洁性:代码更易读,减少错误
底层原理
范围 for 循环会遍历给定容器(或数组)中的每一个元素。在每次迭代中,它会将当前元素复制到循环变量中(注意:这里是复制)。如果你希望避免复制,特别是当容器元素较大时,可以使用引用(如 auto&
或 const auto&
)。
编译器将范围 for 转换为迭代器操作:
// 原始代码
for (auto x : container) { ... }// 等效的传统代码
for (auto it = begin(container); it != end(container); ++it) {auto x = *it; // 注意:这里是值拷贝!...
}
使用示例
示例 1:遍历数组
int numbers[] = {10, 20, 30, 40};// 传统 for 循环
for (int i = 0; i < 4; ++i) {cout << numbers[i] << " ";
}// 范围 for 循环(更简洁!)
for (int num : numbers) {cout << num << " ";
}
// 输出:10 20 30 40
示例 2:遍历 vector
#include <vector>
#include <iostream>
using namespace std;int main() {vector<string> fruits = {"Apple", "Banana", "Cherry"};// 使用 auto 自动推断类型for (auto fruit : fruits) {cout << fruit << " ";}// 输出:Apple Banana Cherry
}
修改元素(使用引用)
若需修改容器中的元素,需使用引用 &
:
vector<int> scores = {80, 90, 70};// 给每个成绩加10分
for (auto& score : scores) { // 注意 & 符号score += 10;
}// 验证结果
for (auto s : scores) {cout << s << " "; // 输出:90 100 80
}
只读场景(使用 const 引用)
当不需要修改元素时,使用 const auto&
避免复制开销:
vector<string> names = {"Alice", "Bob", "Charlie"};// 高效只读访问(尤其对大型对象)
for (const auto& name : names) {cout << name.length() << " "; // 输出:5 3 7
}
支持的数据类型
范围 for 循环可用于:
- 原生数组(如
int arr[5]
) - STL 容器(
vector
,list
,map
,set
等) - 自定义类型(需实现
begin()
和end()
成员函数) - 初始化列表(如
{1,2,3}
)
注意事项
-
容器必须支持迭代器:范围 for 循环内部使用迭代器,因此容器必须具有
begin()
和end()
成员函数,或者是数组。 -
不能修改容器结构:在范围 for 循环中,不能添加或删除容器中的元素,否则可能导致迭代器失效,引发未定义行为。
-
元素访问方式:
-
使用
auto
:创建元素的副本(适用于基本类型或需要修改但不影响原容器的情况)。 -
使用
auto&
:引用元素,可以修改元素(修改会影响原容器)。 -
使用
const auto&
:常量引用,只读且避免复制(适用于大对象或只读遍历)。
经典应用场景
- 遍历数组/容器处理数据
- 配合 STL 算法快速操作
- 处理字符串字符:
string msg = "Hello"; for (char c : msg) {cout << c << "-"; // 输出:H-e-l-l-o- }
建议:在 C++11 及以上版本中,优先使用范围 for 替代传统 for 循环,代码更简洁安全。掌握后你会爱上它!