代码仓库shanchuann/CPP-Learninng

在C++中,范围for循环(range-based for loop) 是C++11引入的特性,专门用于便捷地遍历容器(如vectorlist)、原生数组或其他可迭代对象中的所有元素,大幅简化了遍历代码的写法。

基本语法

范围for循环的核心是“遍历整个范围的元素”,语法格式如下:

1
2
3
for (元素类型 变量名 : 可迭代对象) {
// 循环体(使用变量名访问当前元素)
}
  • 元素类型:当前遍历元素的类型(可使用auto自动推导,更简洁)。
  • 变量名:用于接收当前遍历到的元素(相当于“临时变量”)。
  • 可迭代对象:需要遍历的容器(如vector)、数组、字符串(string)等(本质是支持begin()end()迭代器的对象)。

工作原理

范围for循环本质上是通过迭代器实现的:编译器会自动调用可迭代对象的begin()end()方法,获取遍历的起始和结束位置,然后依次取出每个元素赋值给循环变量,直到遍历结束。

简单说:无需手动控制索引或迭代器,自动遍历所有元素

常用场景与示例

1. 遍历原生数组

1
2
3
4
5
6
7
8
9
10
11
12
#include <iostream>
using namespace std;

int main() {
int arr[] = {10, 20, 30, 40, 50};

// 遍历数组中的每个元素(用auto自动推导类型为int)
for (auto num : arr) {
cout << num << " "; // 输出:10 20 30 40 50
}
return 0;
}

2. 遍历STL容器(如vector

1
2
3
4
5
6
7
8
9
10
11
12
13
#include <iostream>
#include <vector>
using namespace std;

int main() {
vector<string> fruits = {"apple", "banana", "cherry"};

// 遍历vector中的字符串
for (const auto& fruit : fruits) { // 用const&避免拷贝,提高效率
cout << fruit << " "; // 输出:apple banana cherry
}
return 0;
}

3. 修改容器中的元素(需用引用&

如果需要在循环中修改原容器的元素,必须用引用(& 接收元素(否则只是修改临时变量,不影响原容器)。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#include <iostream>
#include <vector>
using namespace std;

int main() {
vector<int> nums = {1, 2, 3, 4};

// 用引用&接收元素,修改会影响原vector
for (auto& num : nums) {
num *= 2; // 每个元素乘以2
}

// 再次遍历查看结果
for (auto num : nums) {
cout << num << " "; // 输出:2 4 6 8
}
return 0;
}

注意:

  1. 不能修改容器大小:循环过程中禁止添加(如push_back)或删除(如erase)元素,否则会导致迭代器失效,引发未定义行为。

    1
    2
    3
    4
    vector<int> v = {1,2,3};
    for (auto x : v) {
    v.push_back(4); // 错误!修改容器大小会导致循环异常
    }
  2. auto的使用:推荐用auto自动推导元素类型,减少代码冗余(尤其容器元素类型复杂时,如map<int, string>的元素类型是pair<const int, string>)。

  3. const与引用的配合:遍历常量容器(如const vector<int>)或不需要修改元素时,用const auto&可以避免元素拷贝,提升性能。

与传统for循环的对比

传统for循环需要手动控制索引或迭代器,代码较繁琐;范围for循环更简洁、可读性更高。

例如遍历vector<int> v

  • 传统循环(索引):
    1
    2
    3
    for (int i = 0; i < v.size(); ++i) {
    cout << v[i] << " ";
    }
  • 传统循环(迭代器):
    1
    2
    3
    for (auto it = v.begin(); it != v.end(); ++it) {
    cout << *it << " ";
    }
  • 范围for循环:
    1
    2
    3
    for (auto x : v) {
    cout << x << " ";
    }