C++中迭代器 for 循环

一、 解释说明

在C++中,传统的迭代器方式 for 循环(即使用迭代器显式控制容器遍历的方式)通常用于对容器进行精细控制,比如提到的 ++it 和 it = edges.begin()。这些操作可以用于多种场景,尤其是在需要修改迭代器的状态或实现更复杂的遍历逻辑时。

二、传统迭代器方式 for 循环概述

通常,传统的迭代器 for 循环是这样的

for (auto it = container.begin(); it != container.end(); ++it) {
    // 对容器的每个元素执行操作
}

这类循环通常适用于需要对容器进行精确控制的场景,例如修改容器元素、跳过某些元素,或者进行多次复杂的遍历。

三、为什么会用 ++it 和 it = edges.begin()?

  • ++it 在循环体内:在循环中使用 ++it 是一种常见的迭代器自增方式,通常用于遍历容器中的每个元素。如果在循环内部出现 ++it,这通常是希望手动跳过当前元素或者实现更复杂的遍历策略。
  • it = edges.begin() 在循环体内:在某些情况下,你可能需要重置迭代器,重新从容器的起始位置开始遍历。这通常发生在你需要多次遍历容器,或者某种条件满足时需要从头开始新的遍历。

四、具体使用场景和示例

场景 1:跳过特定条件的元素

有时候你可能希望在循环体内通过 ++it 跳过某些元素。例如,跳过满足某个条件的元素,或者有某些特殊的处理逻辑时。

示例:跳过值为负数的元素

#include <iostream>
#include <vector>

int main() {
    std::vector<int> numbers = {10, -2, 30, -4, 50};
    
    for (auto it = numbers.begin(); it != numbers.end(); ++it) {
        if (*it < 0) {
            // 如果元素小于0,跳过当前元素
            ++it;
            if (it != numbers.end()) {
                std::cout << "Skipped negative, current: " << *it << std::endl;
            }
            continue;
        }
        std::cout << *it << " ";  // 输出 正常遍历正数
    }
    
    return 0;
}

在这个例子中,当 it 指向一个负数时,我们通过 ++it 跳过该元素,继续遍历容器。

场景 2:需要重置迭代器,从头开始遍历

在某些复杂的遍历场景中,你可能希望在特定条件下重置迭代器并从容器的开始位置重新开始遍历。例如,在一个嵌套循环中,当外层循环某些条件满足时,内层循环可能需要从容器的开始位置重新遍历。

示例:内外层循环中的迭代器重置

#include <iostream>
#include <vector>

int main() {
    std::vector<int> numbers = {1, 2, 3, 4, 5};
    
    // 外层循环遍历数组的每个元素
    for (auto it = numbers.begin(); it != numbers.end(); ++it) {
        std::cout << "Outer Loop, processing: " << *it << std::endl;
        
        // 内层循环,基于外层元素的值决定是否重置迭代器
        if (*it == 3) {
            // 如果遇到值为3的元素,重置迭代器,重新开始从头遍历
            for (auto inner_it = numbers.begin(); inner_it != numbers.end(); ++inner_it) {
                std::cout << "  Inner Loop, processing: " << *inner_it << std::endl;
            }
        }
    }
    
    return 0;
}

在这个例子中,当外层循环的元素为 3 时,内层循环会重置迭代器,并从容器的开始位置重新开始遍历。

场景 3:遍历容器并删除元素

有时候,容器中的元素需要被删除,特别是在遍历时,如果删除元素可能导致一些元素被跳过或访问错误,因此需要手动控制迭代器的步进。在这种情况下,it = container.begin() 和 ++it 可以用来保证元素删除后的正确遍历。

示例:删除满足条件的元素

#include <iostream>
#include <vector>

int main() {
    std::vector<int> numbers = {10, 20, 30, 40, 50};
    
    for (auto it = numbers.begin(); it != numbers.end(); /* do nothing here */) {
        if (*it == 30) {
            // 删除当前元素
            it = numbers.erase(it);  // erase 返回的是下一个有效元素的迭代器
            std::cout << "Deleted 30" << std::endl;
        } else {
            ++it;  // 如果不删除元素,正常递增迭代器
        }
    }

    // 输出剩余的元素
    for (auto it = numbers.begin(); it != numbers.end(); ++it) {
        std::cout << *it << " ";  // 输出 10 20 40 50
    }

    return 0;
}

在这个例子中,使用了 erase 删除容器中的元素。需要注意的是,erase 返回一个指向删除元素后续元素的迭代器,因此在删除元素后,需要更新迭代器,防止跳过某些元素。

场景 4:在循环中动态改变遍历顺序

在某些情况下,你可能希望在遍历过程中基于条件动态改变遍历顺序。例如,可能需要先处理一部分元素,再回到开始处处理另一些元素。

示例:从头到尾和从尾到头遍历容器

#include <iostream>
#include <vector>

int main() {
    std::vector<int> numbers = {1, 2, 3, 4, 5};
    
    // 先从头到尾遍历
    for (auto it = numbers.begin(); it != numbers.end(); ++it) {
        std::cout << *it << " ";
    }
    
    std::cout << "\nNow reverse traversal:\n";
    
    // 重置迭代器并从尾到头遍历
    for (auto it = numbers.end() - 1; it >= numbers.begin(); --it) {
        std::cout << *it << " ";
    }

    return 0;
}

这个例子演示了如何在同一容器上进行两次不同的遍历:一次从头到尾,另一次从尾到头。通过改变迭代器的起始位置和递增/递减方式,动态改变了遍历的顺序。

五、总结

  • ++it 通常用于手动跳过某些元素或精细控制遍历。它使得你可以对每一步的迭代器进行控制,从而更灵活地处理容器元素。
  • it = container.begin() 用于在需要重置迭代器时重新开始遍历。通常出现在嵌套循环、特定条件下需要从头开始重新遍历的情况。
  • 迭代器提供了强大的控制能力,允许你手动控制遍历的过程,适用于更复杂的需求,如删除元素、动态调整遍历顺序等。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值