深入探索C++ STL中的list:一份全面指南及实际案例分析

目录

引言

1. 理解C++中的list

1.1 什么是list?

1.2 使用list的原因

2. 主要特性与接口

2.1 构造函数

2.2 迭代器

2.3 容量函数

2.4 元素访问

3. 修改函数

4. 处理迭代器失效

5. 自定义实现list

自定义list实现示例

6. 探索反向迭代器

7.迭代器失效概述

什么是迭代器失效?

list的迭代器失效特点

1. 迭代器的有效性

插入操作

删除操作

2. 正确处理迭代器失效

3. 反向迭代器的处理

8. list与vector的比较

9. 结论


引言

在C++编程中,STL容器是高效和有效管理代码的重要工具。在这些容器中,list因其特定的特性而脱颖而出,尤其适合频繁插入和删除的场景。本文将深入探讨list容器,分析其结构、用途、优点及与其他STL容器(如vector)的区别,并通过丰富的代码示例帮助读者理解相关概念。

1. 理解C++中的list

1.1 什么是list

C++中的list是一个双向链表,允许高效地在列表的开头、结尾及任意位置插入和删除元素。与vector不同,list不支持随机访问,但在动态内存管理上表现优异,可以最小化重新分配内存的开销。

1.2 使用list的原因

list非常适合频繁插入和删除的场景。例如,在一个待办事项应用中,任务会动态添加和移除,因此使用list能够提高效率。了解其核心优势可以帮助你在项目中更好地选择合适的容器。

2. 主要特性与接口

2.1 构造函数

C++为list提供了多种构造函数:

  • list() – 构造一个空的列表。
  • list(size_type n, const value_type& val) – 构造一个包含n个元素,值为val的列表。
  • list(InputIterator first, InputIterator last) – 用范围[first, last)中的元素构造列表。

示例:

std::list<int> emptyList;
std::list<int> filledList(5, 10); // 创建一个包含5个元素且每个元素值为10的列表
std::list<int> rangeList(filledList.begin(), filledList.end());

2.2 迭代器

list中的迭代器类似于指针,用于访问列表中的元素。C++ list支持:

  • begin()end() 用于正向迭代。
  • rbegin()rend() 用于反向迭代。

示例:

std::list<int> mylist = {1, 2, 3, 4, 5};
for (auto it = mylist.begin(); it != mylist.end(); ++it) {std::cout << *it << " ";
}

2.3 容量函数

  • empty() – 检查列表是否为空。
  • size() – 返回列表中元素的个数。

示例:

std::list<int> mylist;
if (mylist.empty()) {std::cout << "列表为空。\n";
}

2.4 元素访问

  • front() – 访问第一个元素。
  • back() – 访问最后一个元素。

示例:

std::list<int> mylist = {10, 20, 30};
std::cout << "前面元素: " << mylist.front() << ", 后面元素: " << mylist.back() << "\n";

3. 修改函数

list提供多种用于修改内容的函数:

  • push_front()push_back() 用于添加元素。
  • pop_front()pop_back() 用于删除元素。
  • insert()erase() 用于在特定位置插入和删除元素。

示例:

mylist.push_front(5);
mylist.push_back(40);
mylist.insert(std::next(mylist.begin()), 15); // 在第二个位置插入15

4. 处理迭代器失效

vector不同,list的迭代器在插入时仍然有效,只有指向被删除元素的迭代器会失效。这种行为使得list在频繁修改结构的场景中更具优势。

示例场景:

auto it = mylist.begin();
mylist.erase(it++); // 正确处理删除元素

5. 自定义实现list

理解list的一个有效方式是自己实现一个基本版本。这个练习可以帮助你深入理解链表的工作原理。

自定义list实现示例

class Node {
public:int data;Node* next;Node* prev;Node(int val) : data(val), next(nullptr), prev(nullptr) {}
};class CustomList {
private:Node* head;Node* tail;
public:CustomList() : head(nullptr), tail(nullptr) {}void push_back(int val) {Node* newNode = new Node(val);if (!head) {head = tail = newNode;} else {tail->next = newNode;newNode->prev = tail;tail = newNode;}}// 其他功能的实现以展示列表功能
};

6. 探索反向迭代器

反向迭代器允许从尾部向前遍历,适用于在不修改列表的情况下以反向顺序显示元素。

示例:

std::list<int> mylist = {1, 2, 3, 4, 5};
for (auto rit = mylist.rbegin(); rit != mylist.rend(); ++rit) {std::cout << *rit << " ";
}

7.迭代器失效概述

什么是迭代器失效?

迭代器失效是指某个迭代器在执行某些操作后,指向的元素不再有效。例如,若一个元素被删除或容器的结构发生了变化,迭代器可能会指向一个已经不存在的元素,从而导致程序错误。

list的迭代器失效特点

在C++ STL的list中,迭代器的失效行为与其他容器(如vector)有所不同。由于list是一个双向链表,其迭代器在插入操作时不会失效,但在删除操作时,指向被删除元素的迭代器会失效,而其他迭代器则保持有效。这使得list在频繁进行插入和删除操作时比其他容器更为安全。

1. 迭代器的有效性

插入操作

当在list中插入元素时(如使用push_front()push_back()insert()),原有的迭代器不会失效。这是因为list的底层结构允许在任何位置添加新节点,而不会影响其他节点的指向。

示例:

std::list<int> mylist = {1, 2, 3};
auto it = mylist.begin();
mylist.insert(it, 0); // 在开头插入0
// 此时,it依然有效,指向原来的第一个元素1
std::cout << *it; // 输出1
删除操作

然而,当删除元素时,指向被删除元素的迭代器会失效。其他迭代器则不受影响。为了安全地使用迭代器,在删除元素后,应注意更新迭代器的值。

示例:

std::list<int> mylist = {1, 2, 3};
auto it = mylist.begin();
mylist.erase(it); // 删除当前元素1
// 此时,it已经失效,使用it会导致未定义行为
// std::cout << *it; // 不安全的操作

2. 正确处理迭代器失效

为了避免迭代器失效带来的问题,我们可以在删除操作后重新赋值迭代器。通常,我们可以在删除操作的同时使用返回值来更新迭代器。

示例:

std::list<int> mylist = {1, 2, 3, 4, 5};
auto it = mylist.begin();while (it != mylist.end()) {if (*it % 2 == 0) { // 如果元素是偶数it = mylist.erase(it); // 删除元素并更新it} else {++it; // 只在没有删除时才移动迭代器}
}

在上述示例中,erase函数返回一个指向被删除元素后一个元素的迭代器,从而确保了迭代器的有效性。

3. 反向迭代器的处理

反向迭代器(rbegin()rend())的使用和正向迭代器相似,但需要注意的是,在进行删除操作后,同样需要更新迭代器。

示例:

std::list<int> mylist = {1, 2, 3, 4, 5};
auto rit = mylist.rbegin();while (rit != mylist.rend()) {if (*rit % 2 != 0) { // 如果元素是奇数rit = std::prev(mylist.erase(std::next(rit.base()))); // 更新反向迭代器} else {++rit; // 只在没有删除时才移动迭代器}
}

8. listvector的比较

一个常见的问题是使用list还是vector。选择取决于对内存管理、插入/删除效率和访问速度的需求:

  • vector 更适合随机访问,且内存使用高效。
  • list 在需要频繁插入和删除的场景中表现更佳。
特性vectorlist
内存连续的非连续的
随机访问O(1)不支持
插入/删除效率较低(O(n))在任何位置插入/删除效率高(O(1))

9. 结论

理解list为在C++中管理数据结构打开了新的可能性。通过利用list独特的属性,你可以设计高效且响应迅速的应用程序。尝试文中提供的示例,考虑实现你自己的链表,以获得更深入的理解。祝你编程愉快!

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

如若内容造成侵权/违法违规/事实不符,请联系一条长河网进行投诉反馈,一经查实,立即删除!

相关文章

YOLO可视化界面,目标检测前端页面。

使用PySide6/QT实现YOLOv5/v8可视化GUI页面 在人工智能和计算机视觉领域&#xff0c;YOLO&#xff08;You Only Look Once&#xff09;是一种广泛使用的实时目标检测算法。为了直观地展示YOLO算法的检测效果&#xff0c;我们可以使用Python中的PySide6库来创建一个简单的GUI应…

使用vuex动态设置全局字号

1.安装vuex npm install vuexnext --save 2.编写字号设置样式 // 定义字号变量 :root {--font-size: 18px;--font-size-step1: 16px;--font-size-step2: 14px;--font-size-step3: 12px; } // 定义样式&#xff08;全局样式文件&#xff09; body, page {font-size: var(--fo…

编程爱好者的福音:实用技巧与教程

引言 你是否曾经因为代码无法正常运行而感到挫败&#xff1f;或者在面对一行行复杂的代码时&#xff0c;不知道从何下手&#xff1f;编程&#xff0c;这项充满挑战与创造力的技能&#xff0c;往往让人既爱又恨。无论你是刚刚入门的初学者&#xff0c;还是已经具备一定经验的开发…

了解bootstrap改造asp.net core MVC的样式模板

我们都知道&#xff0c;在使用默认的asp.net core MVC模板建立项目的时候&#xff0c;里面的样式是已经事先被写好了的。一般来说都在css目录下的site.css和bootstrap.css及下面的bootstrap.min.css中。我们打开bootstrap这些样式文件&#xff0c;里面有大量的样式类的定义&…

通过使用 FFmpeg 提取某站视频 MV 中的音频为 MP3

无论是为了个人收藏、制作播客还是作为背景音乐&#xff0c;将视频中的音频提取出来都是一个非常实用的技能。本教程中简鹿办公将介绍两种方法来实现这一目标&#xff1a;一种是通过命令行工具 FFmpeg&#xff0c;另一种是使用图形界面工具 - 简鹿音频格式转换器。 使用 FFmpeg…

探秘国际数字影像产业园:数字化转型之路

数字化园区的概念正日益受到全球瞩目&#xff0c;这不仅是科技进步的必然产物&#xff0c;更是现代经济发展的迫切需求。对于国际数字影像产业园而言&#xff0c;打造数字化园区意味着通过尖端科技手段&#xff0c;全面提升园区的管理效率、服务质量及入驻企业和居民的生活体验…

外包干了2年,快要废了。。

先说一下自己的情况&#xff0c;普通本科&#xff0c;在外包干了2年多的功能测试&#xff0c;这几年因为大环境不好&#xff0c;我整个人心惊胆战的&#xff0c;怕自己卷铺盖走人了&#xff0c;我感觉自己不能够在这样蹉跎下去了&#xff0c;长时间呆在一个舒适的环境真的会让一…

5G的发展演进

5G发展的驱动力 什么是5G [远程会议&#xff0c;2020年7月10日] 在来自世界各地的政府主管部门、电信制造及运营企业、研究机构约200多名会议代表和专家们的共同见证下&#xff0c;ITU-R WP 5D#35e远程会议宣布3GPP 5G技术&#xff08;含NB-IoT&#xff09;满足IMT-2020 5G技…

【C++打怪之路Lv14】- “多态“篇

&#x1f308; 个人主页&#xff1a;白子寰 &#x1f525; 分类专栏&#xff1a;重生之我在学Linux&#xff0c;C打怪之路&#xff0c;python从入门到精通&#xff0c;数据结构&#xff0c;C语言&#xff0c;C语言题集&#x1f448; 希望得到您的订阅和支持~ &#x1f4a1; 坚持…

Github 2024-11-05 Python开源项目日报Top10

根据Github Trendings的统计,今日(2024-11-05统计)共有10个项目上榜。根据开发语言中项目的数量,汇总情况如下: 开发语言项目数量Python项目10HTML项目1TypeScript项目1系统设计指南 创建周期:2507 天开发语言:Python协议类型:OtherStar数量:241693 个Fork数量:42010 次…

如何从 Android 图库中恢复误删除的照片

如果您正在阅读这篇文章&#xff0c;那么您肯定意外地从 Android 设备中删除了照片。并且您正在寻找一种简单的方法来恢复 Android 图库中已删除的照片。 从图库恢复已删除的照片 随着技术的进步&#xff0c;现在使用单个设备&#xff08;即 Android 手机&#xff09;&#xf…

ESP-HaloPanel:用 ESP32-C2 打造超低成本智能家居面板

项目简介 在生活品质日益提升的今天&#xff0c;智能家居系统已经走进了千家万户&#xff0c;并逐渐成为现代生活的一部份。与此同时&#xff0c;一款设计精致、体积轻盈、操作简便的全屋智能家居控制面板&#xff0c;已经成为众多家庭的新宠。这种高效、直观的智能化的解决方…

人工智能:重塑未来的力量

华为OD机试 2024E卷题库疯狂收录中&#xff0c;刷题 点这里。 实战项目访问&#xff1a;http://javapub.net.cn/ 人工智能技术的未来&#xff1a;变革与适应 引言 随着人工智能技术的不断发展&#xff0c;我们已经看到了它在各行业带来的巨大变革。从医疗行业的病例诊断到企业…

3D看车如何实现?有哪些功能特点和优势?

3D看车是一种创新的汽车展示方式&#xff0c;它基于网络世界&#xff0c;融合了三维建模与虚拟现实技术&#xff0c;为消费者带来前所未有的真实、立体观车体验。以下是对3D看车的详细解释&#xff1a; 一、3D看车的实现方式 高精度三维建模&#xff1a; 通过高精度三维建模…

消息队列的测试点

消息队列的测试点 一、常用的消息队列产品1、挑战性问题 二、kafka简介三、消息的生产四、消息的存储五、Kafka的特性六、kafka测试要点 一、常用的消息队列产品 基于内存的消息队列 RabbitMQ&#xff1a;适用于处理高并发场景&#xff0c;广泛用于即时消息传递RabbitMQ&…

web实操1——只使用tomcat发布网站

安装tomcat 下载 肯定是去官网&#xff1a; http://tomcat.apache.org/ 下载之后&#xff0c;解压&#xff1a; &#xff01;&#xff01;解压后&#xff1a; logs日志&#xff1a;就是一些输出&#xff0c;输到文本里。 temp:一些临时文件(不用管) webapps:放网站的 work&…

[Unity Demo]从零开始制作空洞骑士Hollow Knight第十七集:制作第二个BOSS燥郁的毛里克

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 前言一、制作游戏第二个BOSS燥郁的毛里克 1.导入素材和制作相关动画1.5处理玩家受到战吼相关行为逻辑处理2.制作相应的行为控制和生命系统管理3.制作战斗场景和战斗…

HarmonyOS开发 - 餐饮APP中多门店多窗口打开实例补充

specified启动模式为指定实例模式&#xff0c;有一些特殊场景&#xff0c;例如多门店应用中每次打开一个门店都希望能新建一个门店实例&#xff0c;而重复打开同一个门店都是同一门店实例。 此篇为餐饮APP中多门店实例的补充内容&#xff0c;以解决同一门店多次点击重复创建新窗…

FreeRTOS 13:FreeRTOS队列的读原理

队列读取消息 FreeRTOS 中用于从队列中读取消息的 API 函数如下表所示&#xff1a; xQueueReceive BaseType_t xQueueReceive( QueueHandle_t xQueue,void * const pvBuffer,TickType_t xTicksToWait ) {BaseType_t xEntryTimeSet pdFALSE;TimeOut_t xTimeOut;Queue_t * con…

山东路远生态科技有限公司竣工投产仪式暨产品发布会圆满举行

第二十届三中全会于2024年7月15日至18日在北京举行。全会审议通过了《关于进一步全面深化改革、推进中国式现代化的决定》。其中提到,“要健全因地制宜发展新质生产力体制机制”。 新质生产力是由技术革命性突破、生产要素创新性配置、产业深度转型升级而催生的当代先进生产力…