C++ Primer : 第九章 : 顺序容器的操作以及迭代器失效问题
顺序容器的添加、访问、删除操作以及forward_list的特殊操作,还有迭代器失效问题。
一、向容器添加元素
// array不支持这些操作
// forward_list有自己撰于的版本的insert和emplace
// forward_list不支持push_back和emplace_back
// vector和string不支持push_front和emplace_front
c.push_back(t); 在c的尾部创建一个值为t或由arg创建的元素
c.emplace_back(arg); 函数返回void
c.push_front(t); 在c的头部创建一个值为t或由arg创建的元素</span>
c.emplace_front(arg); 函数返回void
c.insert(p, t); 在迭代器p指向的元素之前创建一个值为t或有arg创建的元素
c.emplace(p, t); 函数返回指向新添加元素的迭代器
c.insert(p, n, t); 在迭代器p指向元素之前插入n个值为t的元素,函数返回指向新添加的第一个元素的迭代器,若n为0,则返回p
c.insert(p, b, e); 在迭代器p指向元素之前插入迭代器b到e(不包括e)之间的元素,b和e不能指向c中元素,返回新添加的第一个元素的迭代器,若范围为空,则返回p
c.insert(p, il); 在迭代器p指向元素之前插入由花括号包围的初始值列表 il 的元素,函数返回指向新添加的第一个元素的迭代器,若列表为空,则返回p
当容器调用push或insert成员时,这些对象被拷贝到容器中,而进行emplace操作时,则是将参数传递给容器的构造函数,emplace使用这些参数在容器里直接构造一个元素。
因此,emplace的参数必须与元素类型的构造函数的参数相匹配。
二、访问元素
除了array、每个顺序容器都有一个front成员函数,除了forward_list之外的所有顺序容器都有一个back成员函数,这两个操作分别返回首元素和尾元素的引用
// at和下标操作值适用于string、vector、deque和array
// back不适用于forward_list
c.back(); 返回c的尾元素的引用,若c为空,则行为未定义
c.front(); 返回c的首元素的引用,若c为空,则行为未定义
c[n]; 返回c中下标为n的元素的引用,n是一个无符号整数
c.at(n); 返回下标为n的引用。如果下标越界,则抛出一个 out_of_range异常
三、删除元素
// 这些操作不适用于array
// forward_list有特殊版本的erase,并且它不支持pop_back;
// vector和string不支持pop_front
c.pop_back(); 返回c中的尾元素/首元素,若c为空,则函数行为未定义
c.pop_front(); 函数返回void
c.clear(); 删除c中所有元素,返回void
c.erase(p); 删除c中p指向的元素,返回指向被删元素之后元素的迭代器,如果p指向尾元素,则返回尾后迭代器,若p为尾后迭代器,则行为未定义
c.erase(b, e); 删除迭代器b和e(不包括e)之间的元素,返回指向被删元素之后元素的迭代器, 若e为尾后迭代器,则返回e
四、特殊的forward_list操作
由于在单项链表中,没有简单的方法来获取一个元素的前驱,所以在forward_list中定义了首前迭代器。
lst.before_begin(); 返回指向链表首元素之前不存在的元素的迭代器,c开头的是const_iterator版本
lst.cbefore_begin(); 不能解引用此迭代器 lst.inert_after(p, t); 在迭代器p之后插入元素,t是一个对象
lst.inert_after(p, n, t); n是数量
lst.inert_after(p, b, e); b、e表示范围的一对迭代器(不能指向lst)
lst.inert_after(p, il); il是一个花括号的初始化列表,返回一个指向插入的最后一个元素的迭代器,如果范围为空,返回p,如果p为尾后迭代器,则行为未定义
lst.emplace_after(p, arg); 在p指向的位置之后插入由arg构造的元素,返回指向这个新元素的迭代器,如果p是尾后迭代器,则行为未定义
lst.erase_after(p); 删除p之后的元素,或删除b到e(不包括e)之间的元素,返回一个指向被删元素之后元素的迭代器
lst.erase_after(b, e); 如果不存在这样的元素,返回尾后迭代器,若p指向lst的尾元素,或p是lst的尾后迭代器,则行为未定义。
在forwar_list中添加或删除元素时,我们要关注的是:指向要处理的元素的迭代器和其前驱迭代器。
例:从forward_list中删除奇数
forward_list<int> flst = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
auto prev = flst.before_begin(); // 获取首前迭代器
auto curr = flst.begin();
while (curr != flst.end()){
if(*curr % 2)
curr = flst.erase_after(prev); // 删除当前元素,将curr定位到新的第一个元素
else
prev = curr ++; // 移动首前元素和当前元素
}
五、改变容器大小
// resize不适用于array
c.resize(n); 调整c的大小为n个元素,若n < c.size(); 则多出的元素被丢弃,否则对新添加的元素进行值初始化
c.resize(n, t); 调整c的大小为n个元素,任何新添加的元素都被初始化为t
// 如果resize缩小了容器,则指向被删除的元素的迭代器、引用和指针都会失效,对vector、string和deque进行resize可能导致迭代器、引用和指针失效
六、容器操作和迭代器失效问题
向容器中添加元素后:
1. 如果容器时vector或string,且存储空间被重新分配,则指向容器的迭代器、指针和引用都会失效,如果存储空间未重新分配,则指向插入元素之前的迭代器、指针和引用都有效,指向插入元素之后元素的迭代器、指针和引用都会失效。
2. 对于deque,插入到除首尾位置之外的任何位置都会导致迭代器、引用和指针失效,如果在首尾位置添加元素,迭代器会失效,但指向存在的元素的引用和指针不会失效。
3. 对于list和forward_list,指向容器的迭代器(包括尾后迭代器和首前迭代器)、指针和引用都有效
容器在删除元素后:
1. 对于list和forward_list,指向容器的迭代器(包括尾后迭代器和首前迭代器)、指针和引用都有效
2. 对于deque,如果在首尾之外的任何位置删除元素,那么指向删除元素外其他元素的迭代器、引用和指针也会失效。如果是删除deque的尾元素,则尾后迭代器失效,但其他迭代器、引用和指针不受影响; 如果删除首元素,这些也不会受影响。
3. 对于vector和string,指向被删除元素之前元素的迭代器、引用和指针扔有效
当我们删除元素时,尾后迭代器总是会失效!
因此,必须保证每次改变容器的操作之后都正确的重新定位迭代器,还有,不要保存end返回的尾后迭代器。
C++ Primer : 第九章 : 顺序容器的操作以及迭代器失效问题的更多相关文章
- C++ Primer : 第九章 : 顺序容器的定义、迭代器以及赋值与swap
顺序容器属于C++ STL的一部分,也是非常重要的一部分. 顺序容器包括: std::vector,包含在头文件<vector>中 std::string, 包含在头文件<strin ...
- C++ Primer 第九章 顺序容器
由于书籍上写的已经很经典了,故大部分用图片的形式来阐述概念,代码纯手打进行验证. 1.顺序容器类型:vector.deque.list.forword_list.array.string. 2.顺序容 ...
- C++ Primer 读书笔记: 第9章 顺序容器
第9章 顺序容器 引: 顺序容器: vector 支持快速随机访问 list 支持快速插入/删除 deque 双端队列 顺序容器适配器: stack 后进先出栈 queue 先进先出队列 priori ...
- [C++ Primer] 第9章: 顺序容器
顺序容器概述 顺序容器的类型有: 类型 说明 vector 可变长度数组. 支持快速随机访问. deque 双端队列. 支持快速随机访问. list 双向链表. 只支持双向顺序访问. forward_ ...
- 《C++ Primer》笔记 第9章 顺序容器
顺序容器类型 类型 解释 vector 可变大小数组.支持快速随机访问.在尾部之外的位置插入或删除元素可能很慢 deque 双端队列.支持快速随机访问.在头尾位置插入.删除速度很快 list 双向链表 ...
- cb09a_c++_顺序容器的操作2-在顺序容器中添加元素_插入数据
cb09a_c++_顺序容器的操作2在顺序容器中添加元素vector不能向前插入数据,list可以用insertc.push_back(t);c.push_front(t);c.insert(p,t) ...
- cb14a_c++_顺序容器的操作7_赋值与交换(swap)_vector转list
cb14a_c++_顺序容器的操作7_赋值与交换(swap) vector数据赋值给list, slist.assign(svec.begin(), svec.end());//这样可以转 svec- ...
- ca13a_c++_顺序容器的操作6删除元素
/*ca13a_c++_顺序容器的操作6删除元素c.erase(p) //删除迭代器p指向的位置c.erase(b,e) //删除b to e之间的数据,迭代器b包括,e不包括c.clear()//删 ...
- ca12a_c++顺序容器的操作5_访问容器中的数据元素
ca12a_c++顺序容器的操作5_访问容器中的数据元素访问元素:c.back()..显示最后一个数据c.front() ..显示第一个数据c[n],n就是下标,适合vector与dequec.at( ...
随机推荐
- Redis系列-存储篇hash主要操作函数小结
阳光透过玻璃,洒在身上,一杯暖茶在手,说不尽的安逸自得,让我有种想再写篇blog的冲动.上篇主要谈了string,这里谈谈hash吧!hash是一些列key value(field value)的映射 ...
- "琳琅满屋"调查问卷 心得体会及结果分析
·关于心得体会 当时小组提出这个校园二手交易市场的时候,就确定了对象范围,仅仅是面向在校大学生,而且在我们之前就已经有了很多成功的商品交易的例子可以让我们去借鉴,再加上我们或多或少的有过网 ...
- Rhel6-集群管理(luci&&ricci)配置文档
理论基础: User → HA → Lb → web → sql → 分布式filesystem ->磁盘I/O 用户 高可用 负载均衡 应用 数据库 mf ...
- 常见的Web负载均衡方法
用户手动选择 通过在主站首页入口提供不同线路,不同服务器链接的方式,来实现负载均衡.在一些提供下载业务的网站中比较常见,如:华军软件园. DNS轮询 大多域名注册商都支持对同一主机名添加多条A记录,这 ...
- 多线程同步内功心法——PV操作上(未完待续。。。)
阅读本篇之前推荐阅读以下姊妹篇: <秒杀多线程第四篇一个经典的多线程同步问题> <秒杀多线程第五篇经典线程同步关键段CS> <秒杀多线程第六篇经典线程同步事件Event& ...
- iOS网页开发技术总结
网页组成 一个有具体功能的完整的网页,一般由3部分组成 HTML:网页的具体内容和结构 CSS:网页的样式(美化网页最重要的一块) JavaScript:网页的交互效果,比如对用户鼠标事件做出响应 H ...
- PAT 07-3 求素数
求素数,这是一个“古老”的问题,每个学过编程的人都应该碰到过,这里是求第M+1到第N个素数,这么经典的问题,当然得给它写上一笔,下面是题设要求及代码实现 /* Name: Copyright: Aut ...
- Javascript ----字符串(String)中的方法
涉及字符串时,常用到的几个方法... --------------------------------------------------------------------------------- ...
- Mysql5.0以下 手工注入
order by 20 www. .com/product/introduction.php?id=-65 UNION SELECT user(),2 www. .com/product/introd ...
- Linux下TC使用说明
Linux下TC使用说明 一.TC原理介绍 Linux操作系统中的流量控制器TC(Traffic Control)用于Linux内核的流量控制,主要是通过在输出端口处建立一个队列来实现流量控制. ...