c++之迭代器

 

目录

 一、迭代器

二、几种常见的迭代器类型

三、使用迭代器时注意事项


 一、迭代器

在C++中,迭代器是一种用于遍历容器元素的对象。迭代器提供了一种通用的方式来访问各种不同类型的容器,如数组、向量、列表、集合和映射等。

使用迭代器可以避免直接操作容器内部的数据结构,从而提高代码的可读性和可维护性。通过迭代器,可以以一种统一的方式来遍历容器,并且可以在遍历过程中对容器进行各种操作,如查找、插入、删除和排序等。

迭代器的基本操作包括解引用、递增和递减。解引用操作用于访问当前迭代器指向的元素,递增和递减操作用于将迭代器移动到容器中的下一个或上一个元素。

#include <iostream>
#include <vector>

using namespace std;

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

    // 遍历vector并输出每个元素的值
    for (auto it = vec.begin(); it != vec.end(); ++it) {
        cout << *it << " ";
    }
    cout << endl;

    // 在vector的末尾插入一个元素
    vec.insert(vec.end(), 6);

    // 遍历vector并输出每个元素的值
    for (auto it = vec.begin(); it != vec.end(); ++it) {
        cout << *it << " ";
    }
    cout << endl;

    // 查找vector中是否存在元素4
    auto it = find(vec.begin(), vec.end(), 4);
    if (it != vec.end()) {
        cout << "Found element 4 at position " << distance(vec.begin(), it) << endl;
    } else {
        cout << "Element 4 not found" << endl;
    }

    return 0;
}

在上面的代码中,我们使用迭代器遍历了一个vector容器,并且输出了每个元素的值。然后,我们在vector的末尾插入了一个新元素,并且再次遍历了vector。

接下来,我们使用STL库中的find函数查找vector中是否存在元素4。如果找到了该元素,则输出它所在的位置;否则输出未找到该元素的信息。

需要注意的是,迭代器不仅可以用于遍历容器元素,还可以用于对容器进行各种操作,如插入、删除和排序等。例如,在vector容器中,我们可以使用insert函数在任意位置插入新元素,使用erase函数删除指定位置的元素,使用sort函数对元素进行排序等。这些操作都可以通过迭代器来实现。

二、几种常见的迭代器类型

在C++中,每种容器都有自己特定的迭代器类型。以下是几种常见的迭代器类型:

  1. begin()end():这是最基本的迭代器类型,用于指向容器中的第一个元素和最后一个元素之后的位置。例如,在vector中,begin() 返回指向第一个元素的迭代器,而 end() 返回指向最后一个元素之后位置的迭代器。

  2. rbegin()rend():这些是反向迭代器类型,用于从容器的末尾向前遍历元素。例如,在vector中,rbegin() 返回指向最后一个元素的迭代器,而 rend() 返回指向第一个元素之前位置的迭代器。

  3. cbegin()cend()crbegin()crend():这些是常量迭代器类型,用于指向容器中的元素,但不允许修改它们的值。这些迭代器可以用于遍历和访问容器中的元素,但不能用于修改它们。

迭代器的常见操作包括:

  1. 解引用:使用*操作符可以访问当前迭代器指向的元素。例如,在vector中,*it 返回当前迭代器 it 指向的元素的值。

  2. 递增和递减:使用 ++ 操作符将迭代器移动到容器中的下一个元素,使用 -- 操作符将迭代器移动到容器中的上一个元素。例如,在vector中,++it 将迭代器 it 移动到下一个元素。

  3. 比较:使用 ==!=<><=>= 等操作符可以比较两个迭代器的位置关系。例如,在vector中,it1 == it2 可以判断迭代器 it1it2 是否指向同一位置。

除了基本操作外,迭代器还可以用于在容器中进行插入、删除和修改等操作。例如,在vector中,我们可以使用 insert() 函数在任意位置插入新元素,使用 erase() 函数删除指定位置的元素,并且可以通过迭代器来修改容器中的元素的值。

总结起来,迭代器是一种强大的工具,它提供了一种通用而灵活的方式来遍历和操作容器中的元素。通过迭代器,我们可以在不知道容器内部数据结构的情况下访问和修改容器中的数据,从而提高代码的可读性和可维护性。

假设我们有一个存储学生信息的vector容器,每个学生包含姓名和年龄两个属性。我们希望通过遍历容器,找到年龄最大的学生并输出其姓名和年龄信息。

#include <iostream>
#include <vector>

using namespace std;

struct Student {
    string name;
    int age;
};

int main() {
    vector<Student> students = {{"Alice", 20}, {"Bob", 19}, {"Charlie", 21}, {"David", 18}};

    // 定义一个迭代器来指向年龄最大的学生
    auto maxAgeStudent = students.begin();

    // 遍历容器,找到年龄最大的学生
    for (auto it = students.begin(); it != students.end(); ++it) {
        if (it->age > maxAgeStudent->age) {
            maxAgeStudent = it;
        }
    }

    // 输出年龄最大的学生的姓名和年龄
    cout << "The oldest student is: " << maxAgeStudent->name << ", " << maxAgeStudent->age << " years old." << endl;

    return 0;
}

在上述代码中,我们定义了一个名为Student的结构体,用于表示学生的姓名和年龄属性。然后,我们创建了一个存储学生信息的vector容器,并初始化了几个学生对象。

接下来,我们使用迭代器遍历整个学生容器,并通过比较年龄的方式找到年龄最大的学生。在遍历过程中,我们将迭代器 maxAgeStudent 指向年龄最大的学生。

最后,我们通过解引用迭代器,输出了年龄最大的学生的姓名和年龄信息。

运行上述代码,输出将是:

The oldest student is: Charlie, 21 years old.

这个案例展示了如何使用迭代器遍历容器,并根据具体需求对容器中的元素进行操作和处理。通过迭代器,我们可以更方便地访问和操作容器中的数据,从而简化了代码的编写和维护过程。

三、使用迭代器时注意事项

当使用迭代器时,有一些注意事项需要记住:

  1. 避免迭代器失效:在对容器进行修改操作(如插入或删除元素)后,迭代器很可能会失效。如果在迭代过程中进行了修改操作,那么后续的迭代器可能无法正常工作或引发未定义行为。因此,在对容器进行修改操作之后,应该谨慎使用之前的迭代器。
  2. 小心解引用空迭代器:在使用迭代器之前,确保它不是空迭代器(指向容器之外的位置)。解引用空迭代器将导致未定义行为。
  3. 使用合适的迭代器类型:不同的容器类型有不同的迭代器类型,确保使用正确的迭代器类型来遍历和操作容器。例如,使用begin()end()来遍历大多数容器,但对于std::list,还可以使用++--操作符来移动迭代器。
  4. 迭代器失效:在使用迭代器遍历容器时,如果在遍历过程中对容器进行了插入、删除等修改操作,可能会导致迭代器失效。失效意味着迭代器不再指向有效的元素位置,进而可能导致未定义行为。为了避免这种情况,可以使用插入和删除操作后返回的新的迭代器或者使用智能迭代器(如std::list中的迭代器)。
  5. const 迭代器:对于容器中的 const 元素,应该使用 const 迭代器进行访问。例如,在 const vector 中使用 begin() 返回的是一个 const_iterator,它只能用于访问元素,而不能修改元素的值。
  6. 迭代器范围:在使用迭代器进行遍历时,要确保迭代器不会超出容器的有效范围。比如,当迭代器指向容器的最后一个元素时,对其进行递增操作将导致越界。因此,在编写代码时要小心处理迭代器的范围。
  7. 安全删除:删除容器中的元素时,要注意使用 erase() 函数返回的新的迭代器来更新迭代器,并防止迭代器失效。例如,在删除 vector 中的元素后,应该将迭代器更新为 erase() 返回的新的迭代器。
  8. 多线程安全:在多线程环境下使用迭代器时,要注意保护共享数据的访问。如果多个线程同时修改容器,可能导致迭代器失效或者产生竞争条件。可以使用互斥锁等机制来保护迭代器的访问。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/294037.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

c++牛客总结

一、c/c语言基础 1、基础 1、指针和引用的区别 指针是一个新的变量&#xff0c;指向另一个变量的地址&#xff0c;我们可以通过这个地址来修改该另一个变量&#xff1b; 引用是一个别名&#xff0c;对引用的操作就是对变量本身进行操作&#xff1b;指针可以有多级 引用只有一…

python股票分析挖掘预测技术指标知识大全(1)

本人股市多年的老韭菜&#xff0c;各种股票分析书籍&#xff0c;技术指标书籍阅历无数&#xff0c;萌发想法&#xff0c;何不自己开发个股票预测分析软件&#xff0c;选择python因为够强大&#xff0c;它提供了很多高效便捷的数据分析工具包&#xff0c; 我们已经初步的接触与…

leetcode 每日一题 2024年01月01日 经营摩天轮的最大利润

题目 1599 经营摩天轮的最大利润 你正在经营一座摩天轮&#xff0c;该摩天轮共有 4 个座舱 &#xff0c;每个座舱 最多可以容纳 4 位游客 。你可以 逆时针 轮转座舱&#xff0c;但每次轮转都需要支付一定的运行成本 runningCost 。摩天轮每次轮转都恰好转动 1 / 4 周。 给你…

LeetCode 2487. 从链表中移除节点:单调栈

【LetMeFly】2487.从链表中移除节点&#xff1a;单调栈 力扣题目链接&#xff1a;https://leetcode.cn/problems/remove-nodes-from-linked-list/ 给你一个链表的头节点 head 。 移除每个右侧有一个更大数值的节点。 返回修改后链表的头节点 head 。 示例 1&#xff1a; 输…

【RocketMQ每日一问】RocketMQ中raft的应用?

1.rocketmq中raft算法实现方式 RocketMQ 中实现 Raft 算法的模块是 DLedger&#xff0c;它是一种基于 Raft 协议的分布式日志存储模式&#xff0c;用于提供高可用性和数据一致性的保证&#xff0c;保证消息的可靠性和持久化存储。 在 DLedger 中&#xff0c;每个节点都维护着…

IDEA安装教程及使用

一、IDEA简介 ​ IDEA全称IntelliJ IDEA&#xff0c;是用于Java语言开发的集成环境&#xff0c;它是业界公认的目前用于Java程序开发最好的工具。 集成环境&#xff1a;把代码编写&#xff0c;编译&#xff0c;执行&#xff0c;调试等多种功能综合到一起的开发工具。 二、ID…

【软件系统架构设计】期末复习题目汇总:简答+应用

电子科技大学软件系统架构设计2023年秋期末考试复习题目汇总 目录 系统分析与设计概述 面向对象建模语言 系统规划 系统需求分析 系统架构设计 软件建模详细设计 设计模式 用户界面设计 系统分析与设计概述 信息系统的 6 种类型&#xff0c;举例说明&#xff1f; 信息…

一个人,2 年时间,每月赚 6w 美金,独立开发者故事丨 RTE 开发者日报 Vol.120

开发者朋友们大家好&#xff1a; 这里是 「RTE 开发者日报」 &#xff0c;每天和大家一起看新闻、聊八卦。我们的社区编辑团队会整理分享 RTE &#xff08;Real Time Engagement&#xff09; 领域内「有话题的 新闻 」、「有态度的 观点 」、「有意思的 数据 」、「有思考的 文…

探讨芯片封装的技术、工艺以及与之相关的知识

芯片封装作为芯片技术中的重要环节&#xff0c;扮演着保护和连接芯片的关键角色。通过封装工艺&#xff0c;芯片能够与外界进行通信并在实际应用中发挥作用。本文将深入探讨芯片封装的技术、工艺以及与之相关的知识。 芯片封装的概念与意义 芯片封装是指将芯片封装在特定的封…

【算法系列 | 12】深入解析查找算法之—斐波那契查找

序言 心若有阳光&#xff0c;你便会看见这个世界有那么多美好值得期待和向往。 决定开一个算法专栏&#xff0c;希望能帮助大家很好的了解算法。主要深入解析每个算法&#xff0c;从概念到示例。 我们一起努力&#xff0c;成为更好的自己&#xff01; 今天第12讲&#xff0c;讲…

嵌套调用和链式访问

嵌套调用 嵌套调用就是函数之间的互相调用&#xff0c;每个函数就是⼀个乐高零件&#xff0c;正是因为多个乐高的零件互相无缝的配合才能搭建出精美的乐高玩具&#xff0c;也正是因为函数之间有效的互相调用&#xff0c;最后写出来了相对大型的程序。 假设我们计算某年…

git 回退版本

git 回退版本 1.查看记录 git log 2.如何回退 git reset --hard commit_id commit_id为上面加深的id 3.强制提交 git push origin HEAD --force

中国九大农业区划数据,shp格式,1982年数据,面形式,数据已可视化

中国九大农业区划包含东北平原区 、北方干旱半干旱区 、黄淮海平原区 、黄土高原区 、青藏高原区 、长江中下游地区 、四川盆地及周边地区 、云贵高原区 、华南区&#xff0c;以下为该数据信息&#xff1a; 基本信息. 数据名称: 中国九大农业区划数据 数据格式: Shp 数据…

自动驾驶状态观测1-坡度估计

背景 自动驾驶坡度对纵向的跟踪精度和体感都有一定程度的影响。行车场景虽然一般搭载了GPS和IMU设备&#xff0c;但pitch角一般不准&#xff0c;加速度也存在波动大的特点。泊车场景一般在室内地库&#xff0c;受GPS信号遮挡影响&#xff0c;一般无法获取高程和坡度。搭载昂贵…

更新!又10本期刊被踢,Scopus期刊目录-第九版(附下载)

Scopus概况 Scopus是Elsevier创立于2004年的摘要和引文数据库&#xff0c;同时也是全世界最大的摘要和引文数据库&#xff0c;涵盖了丛书、期刊和行业期刊这三种资源类型。 截止到2023年8月&#xff0c;Scopus期刊目录中共包含期刊44049本。 Scopus与SCIE或SSCI一样&#xf…

conda

一、安装 推荐清华源 https://mirrors.tuna.tsinghua.edu.cn/anaconda/miniconda/?CN&OD选择版本 Miniconda3-py39_4.12.0-MacOSX-arm64.pkg测试命令 conda help二、更换仓库 配置加速 https://mirrors.tuna.tsinghua.edu.cn/help/anaconda/没有 .condarc 文件则执行…

Java新手必看:final关键字的正确使用技巧,让你避免常见错误!

在Java中&#xff0c;final关键字表示“最终的”或“不可变的”&#xff0c;用于标记变量、方法和类。它有助于确保数据的安全性、API设计的稳定、性能优化以及支持设计模式。当变量被标记为final时&#xff0c;其值不可更改&#xff0c;保障了数据的完整性和安全性。在API或库…

CMake报错集锦

一、报错1 -bash: pybind11-config: command not found CMake Error at CMakeLists.txt:33 (find_package):By not providing "Findpybind11.cmake" in CMAKE_MODULE_PATH this project hasasked CMake to find a package configuration file provided by "pyb…

Spring事务(2):声明式事务管理案例-转账(xml、注解)

1 编写转账案例&#xff0c;引出事务管理问题 需求&#xff1a;账号转账&#xff0c;Tom账号取出1000元&#xff0c;存放到Jack账号上 1.1 建表脚本&#xff08;MySQL&#xff09; CREATE TABLE t_account (id INT(11) NOT NULL AUTO_INCREMENT,name VARCHAR(20) NOT NULL,m…

mysql 添加用户并分配select权限

1.root用户先登录或者在可执行界面 1.1 选择mysql 点击mysql 或者在命令行 use mysql 1.2创建用户 CREATE USER username% IDENTIFIED BY password; 备注1&#xff1a;%替换为可访问数据库的ip&#xff0c;例如“127.0.0.1”“192.168.1.1”&#xff0c;使用“%”表示不限制…