《C++11》范围基 for 循环详解_c++

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::liststd::setstd::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. 优缺点分析

优点

  1. 简洁性:相比传统的 for 循环,范围基 for 循环的语法更加简洁,减少了代码的复杂性。
  2. 安全性:范围基 for 循环自动处理容器的边界,避免了因手动管理索引而可能导致的越界错误。
  3. 可读性:代码更易于理解,特别是对于不熟悉 C++ 的开发者,范围基 for 循环的意图更加明确。

缺点

  1. 不支持逆向遍历:范围基 for 循环只能从头到尾遍历容器,无法直接支持逆向遍历。
  2. 无法获取索引:在范围基 for 循环中,无法直接获取当前元素的索引,如果需要索引,仍需使用传统的 for 循环。
  3. 不适用于所有场景:在某些情况下,例如需要在遍历过程中删除元素时,范围基 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: 15

9.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 6

9.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 循环都能帮助我们更好地管理和操作数据。