
C++11 引入的范围基 for 循环(Range-based for loop)是一种简洁而强大的语法,用于遍历容器(如数组、向量、列表、集合等)。它不仅提高了代码的可读性和可维护性,还减少了常见的错误。本文将深入探讨范围基 for 循环的语法、用法、优缺点、适��场景以及一些实际应用示例。
1. 范围基 for 循环的基本语法
范围基 for 循环的基本语法如下:
for (declaration : container) {
// 循环体
}- declaration:定义一个变量,用于表示当前循环中容器的元素。可以是值、引用或指针。
- container:要遍历的容器(如数组、向量、集合等)。
示例
以下是一个简单的示例,展示如何使用范围基 for 循环遍历一个整数向量:
#include <iostream>
#include <vector>
int main() {
std::vector<int> numbers = {1, 2, 3, 4, 5};
for (int num : numbers) {
std::cout << num << " ";
}
return 0;
}输出:
1 2 3 4 5在这个例子中,num 变量依次获取 numbers 向量中的每一个元素,循环体内的代码将这些元素打印出来。
2. 使用 const 引用提高性能
在遍历大型容器时,使用 const 引用可以避免不必要的拷贝,从而提高性能。以下是一个示例:
#include <iostream>
#include <vector>
int main() {
std::vector<std::string> fruits = {"Apple", "Banana", "Cherry"};
for (const std::string& fruit : fruits) {
std::cout << fruit << " ";
}
return 0;
}在这个例子中,fruit 是一个 const 引用,避免了对每个字符串的拷贝,提升了性能。
3. 修改容器元素
如果需要在循环中修改容器的元素,可以使用非 const 引用:
#include <iostream>
#include <vector>
int main() {
std::vector<int> numbers = {1, 2, 3, 4, 5};
for (int& num : numbers) {
num *= 2; // 将每个元素乘以 2
}
for (const int& num : numbers) {
std::cout << num << " ";
}
return 0;
}输出:
2 4 6 8 10在这个例子中,num 是一个非 const 引用,因此可以直接修改 numbers 向量中的元素。
4. 适用于其他 STL 容器
范围基 for 循环不仅适用于 std::vector,还可以用于其他 STL 容器,如 std::list、std::set、std::map 等。以下是一个使用 std::map 的示例:
#include <iostream>
#include <map>
int main() {
std::map<std::string, int> age = {{"Alice", 30}, {"Bob", 25}, {"Charlie", 35}};
for (const auto& pair : age) {
std::cout << pair.first << " is " << pair.second << " years old." << std::endl;
}
return 0;
}输出:
Alice is 30 years old.
Bob is 25 years old.
Charlie is 35 years old.在这个例子中,pair 是一个 std::pair 类型的引用,包含了 map 中的键值对。
5. 遍历数组
范围基 for 循环也可以用于原始数组的遍历。以下是一个示例:
#include <iostream>
int main() {
int arr[] = {10, 20, 30, 40, 50};
for (int num : arr) {
std::cout << num << " ";
}
return 0;
}输出:
10 20 30 40 50在这个例子中,num 变量依次获取数组 arr 中的每一个元素。
6. 使用 auto 关键字
在范围基 for 循环中,使用 auto 关键字可以简化类型声明,尤其是在处理复杂类型时。以下是一个示例:
#include <iostream>
#include <vector>
int main() {
std::vector<std::pair<std::string, int>> people = {{"Alice", 30}, {"Bob", 25}, {"Charlie", 35}};
for (const auto& person : people) {
std::cout << person.first << " is " << person.second << " years old." << std::endl;
}
return 0;
}在这个例子中,auto 关键字自动推导出 person 的类型为 std::pair<std::string, int>。
7. 处理嵌套容器
范围基 for 循环也可以用于遍历嵌套容器。以下是一个示例,展示如何遍历一个包含向量的向量:
#include <iostream>
#include <vector>
int main() {
std::vector<std::vector<int>> matrix = {
{1, 2, 3},
{4, 5, 6},
{7, 8, 9}
};
for (const auto& row : matrix) {
for (int num : row) {
std::cout << num << " ";
}
std::cout << std::endl;
}
return 0;
}输出:
1 2 3
4 5 6
7 8 9在这个例子中,外层循环遍历 matrix 的每一行,内层循环遍历每一行的元素。
8. 优缺点分析
优点
- 简洁性:相比传统的 for 循环,范围基 for 循环的语法更加简洁,减少了代码的复杂性。
- 安全性:范围基 for 循环自动处理容器的边界,避免了因手动管理索引而可能导致的越界错误。
- 可读性:代码更易于理解,特别是对于不熟悉 C++ 的开发者,范围基 for 循环的意图更加明确。
缺点
- 不支持逆向遍历:范围基 for 循环只能从头到尾遍历容器,无法直接支持逆向遍历。
- 无法获取索引:在范围基 for 循环中,无法直接获取当前元素的索引,如果需要索引,仍需使用传统的 for 循环。
- 不适用于所有场景:在某些情况下,例如需要在遍历过程中删除元素时,范围基 for 循环可能不适用。
9. 实际应用示例
9.1 统计容器中的元素
以下示例展示如何使用范围基 for 循环统计容器中元素的总和:
#include <iostream>
#include <vector>
int main() {
std::vector<int> numbers = {1, 2, 3, 4, 5};
int sum = 0;
for (int num : numbers) {
sum += num;
}
std::cout << "Total sum: " << sum << std::endl;
return 0;
}输出:
Total sum: 159.2 过滤容器中的元素
以下示例展示如何使用范围基 for 循环过滤容器中的元素:
#include <iostream>
#include <vector>
int main() {
std::vector<int> numbers = {1, 2, 3, 4, 5, 6};
std::vector<int> evenNumbers;
for (int num : numbers) {
if (num % 2 == 0) {
evenNumbers.push_back(num);
}
}
std::cout << "Even numbers: ";
for (int num : evenNumbers) {
std::cout << num << " ";
}
return 0;
}输出:
Even numbers: 2 4 69.3 结合算法库
范围基 for 循环可以与 C++ 标准库中的算法结合使用,以下示例展示如何使用 std::for_each 和范围基 for 循环:
#include <iostream>
#include <vector>
#include <algorithm>
int main() {
std::vector<int> numbers = {1, 2, 3, 4, 5};
std::for_each(numbers.begin(), numbers.end(), [](int num) {
std::cout << num * 2 << " ";
});
return 0;
}输出:
2 4 6 8 10在这个例子中,使用 std::for_each 和 lambda 表达式遍历并处理容器中的元素。
10. 总结
C++11 的范围基 for 循环为遍历容器提供了一种简洁、安全且高效的方式。通过使用 const 引用和非 const 引用,我们可以灵活地处理容器中的元素。无论是简单的数组还是复杂的 STL 容器,范围基 for 循环都能帮助我们更好地管理和操作数据。
















