当前位置: 首页 > news >正文

C++ 之 【list的简介、list 的构造函数、iterator、容量操作、元素访问、增删查改与迭代器失效】

目录

1.list的介绍

2.list的使用

2.1 构造函数

2.2 iterator 的使用

2.3 容量操作

2.4 元素访问

2.5 增删查改

2.5.1头插头删与尾插尾删

2.5.2 insert 、erase 函数

2.5.3 clear、swap函数

2.5.4 关于find函数

3.迭代器失效


1.list的介绍

(1)list的底层通常实现为带头双向循环链表,支持在任意位置插入、删除

(2)链表中,每个节点包含:一个存储数据的变量和指向前后两个节点的指针

假设节点存储的是int型的数据,则结构如下:

2.list的使用

详细了解请参考文档list - C++ Reference

下面只介绍一些常见接口:

2.1 构造函数

std::list()默认构造函数,创建一个空链表。std::list<int> l1;

std::list(size_type n, 

const T& val = T())   

创建一个包含 n 个元素的链表,所有元素初始化为 valstd::list<int> l3(3, 10); → {10, 10, 10}

template<class InputIt>

std::list(InputIt first, InputIt last)

使用迭代器范围 [first, last) 初始化链表(拷贝范围内的元素)。std::list<int> l4(v.begin(), v.end());(假设 v 是 {1, 2, 3}
std::list(const list& other)拷贝构造函数,创建一个与 other 内容相同的链表(深拷贝)。std::list<int> l5(l4);l5 内容与 l4 相同)

2.2 iterator 的使用

begin()返回指向链表第一个元素的迭代器(若链表为空,返回 end())。正向遍历链表、插入/删除头部元素、作为范围循环的起点。
end()返回指向链表尾后位置的迭代器(不指向任何有效元素,仅用于比较)。标记遍历结束位置、作为范围循环的终点、检查链表是否为空(l.begin() == l.end())。
rbegin()返回指向链表最后一个元素的反向迭代器(逻辑上为链表的“反向开头”)。反向遍历链表、从末尾开始处理元素。
rend()返回指向链表“反向尾后”位置的迭代器(逻辑上为链表的“反向末尾”)。标记反向遍历结束位置、作为反向范围循环的终点。

假设链表被实现为 带头双向循环链表,则迭代器示意如下

总结:

1. begin与end为正向迭代器,对迭代器执行++操作,迭代器向后移动 

2. rbegin与rend为反向迭代器,对迭代器执行++操作,迭代器向前移动

2.3 容量操作

empty() bool检查链表是否为空(无元素)if (l.empty()) { std::cout << "链表为空!"; }
size()size_type返回链表中元素的数量(类型为 std::size_tstd::cout << "链表大小: " << l.size();

2.4 元素访问

front()

返回链表第一个元素的引用

(可修改或读取)。

int first = l.front(); 

或 l.front() = 100;

back()

返回链表最后一个元素的引用

(可修改或读取)。

int last = l.back(); 

或 l.back() += 10;

2.5 增删查改

2.5.1头插头删与尾插尾删

void push_front(const T& value);
 
在链表头部插入元素lt.push_front(1);
void pop_front();删除链表头部元素。lt.pop_front();
void push_back(const T& value);
 
在链表尾部插入元素lt.push_back(1);
void pop_back();删除链表尾部元素。lt.pop_back();

pop_front使begin()迭代器失效,pop_back使end()迭代器失效

其余的不失效

2.5.2 insert 、erase 函数

insert在指定位置 pos 前插入元素(支持单元素、重复元素、范围插入)返回指向新插入元素的迭代器(对单元素插入)原有迭代器不失效
erase删除指定位置或范围的元素(支持单元素删除、范围删除)返回指向被删除元素后一个位置的迭代器。使被删除元素的迭代器失效
void test1(){std::list<int> lst = {1, 2, 3, 4, 5};// 1. 单元素插入(在第二个位置插入 99)auto it = lst.begin();// 手动移动迭代器到第二个位置++it;auto insert_it = lst.insert(it, 99); // 在 it 前插入 99std::cout << "After single insert: ";for (int x : lst) {std::cout << x << " "; // 输出: 1 99 2 3 4 5}std::cout << "\nInserted element: " << *insert_it << std::endl; // 输出: 99// 2. 范围插入(在第三个位置插入数组 {5, 6, 7})int arr[3] = {5, 6, 7};auto range_it = lst.begin();// 手动移动迭代器到第三个位置for(int i = 0; i < 3; ++i){++range_it;}lst.insert(range_it, arr, arr + 3); // 插入数组std::cout << "After range insert: ";for (int x : lst) {std::cout << x << " "; // 输出: 1 99 2 5 6 7 3 4 5}// 3. 填充插入(在末尾插入 3 个 0)lst.insert(lst.end(), 3, 0); // 末尾插入 3 个 0std::cout << "\nAfter fill insert: ";for (int x : lst) {std::cout << x << " ";// 输出: 1 99 2 5 6 7 3 4 5 0 0 0}// 1. 单元素删除(删除值为 99 的元素)auto delete_it = std::find(lst.begin(), lst.end(), 99); // 查找元素if (delete_it != lst.end()) {auto next_it = lst.erase(delete_it); // 删除并返回下一个元素的迭代器std::cout << "After single erase: ";for (int x : lst) {std::cout << x << " "; // 输出: 1 2 5 6 7 3 4 5 0 0 0}std::cout << "\nNext element after erase: " << *next_it << std::endl; // 输出: 2}// 2. 范围删除(删除从第二个到第四个元素)auto start_it = lst.begin();// 手动移动迭代器到第二个位置for (int i = 0; i < 1 && start_it != lst.end(); ++i, ++start_it);auto end_it = lst.begin();// 手动移动迭代器到第五个位置for (int i = 0; i < 4 && end_it != lst.end(); ++i, ++end_it);lst.erase(start_it, end_it); // 删除 [start_it, end_it) 范围内的元素std::cout << "After range erase: ";for (int x : lst) std::cout << x << " "; // 输出: 1 3 4 5 0 0 0// 3. 边界条件:删除 end() 会导致未定义行为// lst.erase(lst.end()); // 错误:不能删除 end()
}

2.5.3 clear、swap函数

void swap(list& other); 交换当前链表与 other 链表的所有元素(包括大小、节点和迭代器有效性)other:待交换的另一个 std::list 对象交换后,原链表的迭代器指向 other 的元素,反之亦然;
void clear();删除链表中的所有元素,释放所有节点内存

所有迭代器/引用失效

(链表变为空)

虽然使用swap函数后,原链表的迭代器指向 other 的元素,反之亦然,

但是开发者不要依赖交换后的迭代器/引用(除非明确知道它们指向另一个链表)

以避免潜在的逻辑错误和未定义行为

2.5.4 关于find函数

std::list 无find成员函数,调用标准库中的find函数即可

3.迭代器失效

操作

失效的

迭代器/指针/引用类型

失效原因避免失效的方法
insert

不失效(插入位置及之前的迭代器、指针、引用

均有效)

std::list 是双向链表,插入操作仅修改相邻节点的指针,不移动现有节点,所以不失效无需特殊处理,直接使用插入后的迭代器继续操作。
erase仅失效被删除节点的迭代器、指针、引用erase 会释放被删除节点的内存,导致指向该节点的迭代器/指针/引用失效。

删除前保存下一个节点的迭代器(如 auto next_it = it; ++next_it;),或使用返回值

it = list.erase(it)

clear所有迭代器、指针、引用均失效clear 会释放链表中所有节点的内存,导致所有迭代器/指针/引用失效。清空后通过 begin()/end() 重新获取迭代器,避免使用旧迭代器。
swap所有迭代器、指针、引用失效(除非交换同一链表)交换后,原链表的迭代器指向 other 的元素,反之亦然。逻辑上所有迭代器失效(内容所属链表已改变)。交换后通过 begin()/end() 重新获取迭代器,避免依赖交换后的迭代器。

相关文章:

  • C++ 之 【模拟实现 list(节点、迭代器、常见接口)】(将三个模板放在同一个命名空间就实现 list 啦)
  • 受限字符+环境变量RCE
  • 代码随想录打卡|Day29 动态规划Part02(不同路径、不同路径2、整数拆分、不同的二叉树搜索)
  • 免费LUT网站
  • 【Docker】使用 jq 管理镜像源
  • C++核心编程:类与对象全面解析
  • uniapp常用
  • 迭代器与生成器
  • 2025A卷-正整数到Excel编号之间的转换
  • 什么是 Web 标准?为什么它们对 SEO 和开发很重要?
  • GitLab CVE-2024-12444 安全漏洞解决方案
  • Vue+Echarts 3D地图效果
  • Java锁的升级流程详解:无锁、偏向锁、轻量级锁、重量级锁
  • YUM/DNF管理工具
  • 用vite动态导入vue的路由配置
  • 递归、搜索和回溯算法《递归》
  • 飞凌嵌入式T527核心板获得【OpenHarmony生态产品兼容性证书】
  • window 图形显示驱动-在 WDDM 1.2 中提供无缝状态转换(下)
  • 关于健身房管理系统前后端软件开发主要功能需求分析
  • 《Astro 3.0岛屿架构让内容网站“脱胎换骨”》
  • 龚正会见委内瑞拉副总统罗德里格斯
  • 【社论】优化限购限行,激发汽车消费潜能
  • 图像编辑新增一款开源模型,阶跃星辰发布Step1X-Edit
  • 美国政府将暂时恢复部分受影响留学生的合法身份,并将制订新标准
  • 迟来的忍者与武士:从《刺客信条:影》论多元话语的争议
  • 龚曙光:散文家永远只有一个视角,就是“我与时代”