• 【C++】迭代器:遍历容器的利器



    当涉及C++中的迭代器时,我们通常指的是容器类的成员类型,它们提供了一种访问容器元素的抽象方式。通过迭代器,我们可以遍历容器中的元素,执行插入、删除和修改等操作,而无需了解容器内部的具体实现细节。本篇博客将介绍C++中迭代器的基本概念、常见用法以及一些实际示例。

    迭代器的基本概念

    在C++中,迭代器是一种类指针的对象,可用于遍历容器中的元素。它提供了对容器内容的间接访问,使得我们可以以统一的方式处理不同类型的容器。每种容器都定义了适合它的迭代器类型,比如std::vector有正向迭代器(iterator)和常量正向迭代器(const_iterator),std::list有双向迭代器(iterator)和常量双向迭代器(const_iterator)。

    迭代器的基本操作

    1. 迭代器的初始化:可以使用容器的成员函数begin()end()来获取迭代器的起始位置和结束位置。

    2. 迭代器的遍历:使用循环结构(如for循环或while循环)和迭代器来遍历容器中的元素。通常使用递增运算符++将迭代器移动到下一个位置,并使用解引用运算符*来访问当前迭代器指向的元素。

    3. 迭代器的比较:可以使用比较运算符(如==、!=、<、>等)来比较迭代器。

    #include 
    #include 
    
    int main() {
        std::vector<int> myVector = {1, 2, 3, 4, 5};
    
        // 比较两个迭代器是否相等
        std::vector<int>::iterator it1 = myVector.begin();
        std::vector<int>::iterator it2 = myVector.begin();
        if (it1 == it2) {
            std::cout << "it1 和 it2 指向同一个元素" << std::endl;
        }
    
        // 判断两个迭代器所指向元素的相对位置
        std::vector<int>::iterator start = myVector.begin();
        std::vector<int>::iterator end = myVector.end();
        if (start < end) {
            std::cout << "start 在 end 之前" << std::endl;
        }
    
        return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    1. 迭代器的操作:可以对迭代器进行一些操作,如迭代器的赋值、增减、解引用等。

    示例代码

    #include 
    #include 
    
    int main() {
        std::vector<int> myVector = {1, 2, 3, 4, 5};
    
        // 声明迭代器
        std::vector<int>::iterator it;
    
        // 遍历输出容器中的元素
        for (it = myVector.begin(); it != myVector.end(); ++it) {
            std::cout << *it << " ";
        }
        
        return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 用auto可以省去声明迭代器
    #include 
    #include 
    
    int main() {
        std::vector<int> myVector = {1, 2, 3, 4, 5};
    
        // 遍历输出容器中的元素
        for (auto it = myVector.begin(); it != myVector.end(); ++it) {
            std::cout << *it << " ";
        }
        
        return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    注意事项

    1. 迭代器的有效性:当容器发生修改时,迭代器可能会失效,因此需要注意在修改容器后更新迭代器。

    2. 边界条件:使用迭代器时需要小心边界条件,确保不会越界访问容器的元素。

    • 以下是一个简单的示例,展示了在不正确地处理迭代器时可能导致的越界访问问题:
    #include 
    #include 
    
    int main() {
        std::vector<int> myVector = {1, 2, 3, 4, 5};
    
        // 错误示例:尝试在循环中删除偶数元素
        for (auto it = myVector.begin(); it != myVector.end(); ++it) {
            if (*it % 2 == 0) {
                myVector.erase(it);  // 删除偶数元素
            }
        }
    
        return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    在上述示例中,我们尝试在循环中使用迭代器遍历 myVector 并删除其中的偶数元素。然而,这样的操作会导致迭代器失效,因为在调用 erase 函数后迭代器 it 将指向一个无效的位置。这种情况下,继续使用失效的迭代器进行遍历或解引用操作将导致未定义的行为,有可能导致程序崩溃或产生错误的结果。

    因此,正确处理迭代器的失效情况对于避免越界访问至关重要。在需要修改容器的同时遍历其中的元素时,通常建议先收集需要删除的元素,然后再进行批量删除,以避免迭代器失效的问题。

    #include 
    #include 
    #include 
    
    int main() {
        std::vector<int> myVector = {1, 2, 3, 4, 5};
    
        // 创建容器来存储需要删除的元素
        std::vector<int> elementsToRemove;
    
        // 收集需要删除的元素
        for (auto it = myVector.begin(); it != myVector.end(); ++it) {
            if (*it % 2 == 0) {
                elementsToRemove.push_back(*it);
            }
        }
    
        // 批量删除需要删除的元素
        for (auto element : elementsToRemove) {
            myVector.erase(std::remove(myVector.begin(), myVector.end(), element), myVector.end());
        }
    
        // 输出删除偶数元素后的 vector
        for (auto num : myVector) {
            std::cout << num << " ";
        }
        std::cout << std::endl;
    
        return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 避免了直接在循环中删除元素导致迭代器失效的问题:
    #include 
    #include 
    
    int main() {
        std::vector<int> myVector = {1, 2, 3, 4, 5};
    
        // 正确写法:使用迭代器擦除元素后,将迭代器指向被删除元素的下一个位置
        for (auto it = myVector.begin(); it != myVector.end(); ) {
            if (*it % 2 == 0) {
                it = myVector.erase(it);  // 删除偶数元素,并将迭代器指向被删除元素的下一个位置
            } else {
                ++it;  // 继续遍历下一个元素
            }
        }
    
        // 输出删除偶数元素后的 vector
        for (auto num : myVector) {
            std::cout << num << " ";
        }
        std::cout << std::endl;
    
        return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23

    结语

    通过迭代器,我们可以方便地遍历和操作容器中的元素,使得C++中的容器类具有了更加灵活和统一的特性。同时,了解迭代器的基本概念和常见用法,对于编写高效、清晰的C++代码至关重要。希望本篇博客能够帮助读者更好地理解C++中迭代器的用法和意义。

  • 相关阅读:
    Redis缓存和数据库一致性、雪崩、穿透、热点key、big key
    【智能优化算法-鲸鱼算法】基于鲸鱼算法求解多目标优化问题附matlab代码(NSWOA)
    Shiro-全面详解(学习总结---从入门到深化)
    Go短网址项目实战---上
    Caffeine本地缓存
    SpringCloud 三种服务调用方式,你学会了吗?
    chatgpt赋能python:Python找零-让你的生活更轻松
    【绝㊙️】三年开发内功心得
    spring cloud+spring boot__基于AOP面向切面编程记录操作日志完整流程记录
    Vita-CLIP: Video and text adaptive CLIP via Multimodal Prompting
  • 原文地址:https://blog.csdn.net/Colorful___/article/details/134470827