C++学习笔记-容器
来源:互联网 发布:cici网络里是什么意思 编辑:程序博客网 时间:2024/05/17 04:05
顺序容器的类型
vector
deque
list
forward_list
array
string
比较:
string和vector中的元素顺序存储,能够快速随机访问。在中间位置添加,插入或删除元素非常耗时
list和forward_list不支持元素的随机访问。为了访问一个元素,必须遍历整个容器。能非常快速地在容器任何位置添加和删除元素
deque能够快速随机访问。在中间位置添加,插入或删除元素的代价可能很高。但是,在deque的两端添加或删除元素都是很快的
array是一种更安全、更容易使用的数组结构。大小固定,不支持添加和删除元素,以及改变容器大小的操作。
确定使用哪种顺序容器
通常,使用vector是最好的选择
如果不确定应该使用哪种容器,那么在程序中只使用vector和list公共的操作,无论最后决定用vector还是决定用list,程序都不用做大的改动。
容器均是模板类。对大多数,但不是所有容器,我们需要提供元素类型信息
vector<int> iv;
迭代器范围
一个迭代器范围用一对迭代器表示。两个迭代器分别指向同一个容器中的元素或者是尾元素之后的位置
假设begin和end构成一个合法的迭代器范围,那么有如下性质
- 若begin和end相等,则范围为空
- 若两者不相等,则范围内至少有一个元素。且begin指向该范围内的第一个元素
- 对begin递增若干次,最终能使得begin==end
容器定义和初始化
默认构造函数
C c; 例vector<int> iv;
将一个容器初始化为另一个容器的拷贝
C c1(c2)或者 C c(beg,end) 例vecor<int> iv2(iv1) 或者vecor<int> iv2(iv1.begin,iv1.end)
当将一个容器初始化为另一个容器的拷贝时,两个容器的容器元素类型和元素类型必须相同。
如果传递迭代器参数来拷贝一个范围,那么只要求被拷贝的元素能转换成要初始化的容器的元素类型。
列表初始化
C c={元素列表};例 vector<int> iv={1,2,3} ,则iv有三个元素
与顺序容器大小相关的构造函数
C seq(n) 其中n是容器大小 例 vector<string> sv(5);
C seq(n,t) 其中n是容器大小,t是元素初始值 例 vector<string> sv(5,"hello");
array的构造函数
除了指定元素类型,同时要指定容器大小
array<int,42> ial; //42个元素都是0
array<int,42> ial={1,2,3} //使用的列表初始化。前三个元素分别是1,2,3,后面的39个元素都是0
可以复制array对象
array<int,42> ial2=ial;
赋值,交换和替换
赋值:
c1=c2;
c1={a,b,c};//array不支持
注意,赋值要求左右两边容器的类型相同,但不要求大小相同。赋值运算后,左右两边容器的大小都等于右边容器大小。
赋值操作适用于所有容器(除array不支持c1={a,b,c}的情形外)
赋值操作会导致指向左边容器内部的迭代器、引用和指针失效
交换
swap(c1,c2);
c1.swqp(c2);
交换c1和c2中的元素。两者必须具有相同的类型,不必拥有相同大小
交换元素的速度比拷贝元素的速度快得多。因为除array外,swap不对任何元素进行拷贝、删除或插入操作。元素本身未交换,只是交换了两个容器的内部数据结构
所有容器都支持
元素没有被移动,所以,除string外,指向容器的迭代器,引用和指针在swap操作之后都不会失效,但是所属的容器改变了。迭代器指向另一个容器的那个位置。
替换
seq.assign(b,e); //b,e是一对迭代器范围
seq.assign(il); //il是初始化列表
seq.assign(n,t) //将seq中的元素替换为n个值为t 的元素
assign操作用参数所指定的元素替换左边容器中的所有元素。要求右边容器的元素类型与左边相容(能转换成左边元素的类型)。右边元素的个数不限制。既可以比左边容器中元素多,也可以比左边容器中元素少。
除array外的所有顺序容器都支持。
关系运算符
所有容器都支持==和!=、除无序关联容器外,所有容器都支持关系运算符(>,>=,<,<=)
关系运算符左右两边的运算对象必须是相同类型的容器。
容器的比较,实际上是其中相应位置的元素的比较。因此,如果元素类型不支持所需运算符,那么容器就不能用相应的运算符进行比较。
顺序容器的操作
添加元素
push_back
除array和forward_list之外,每个顺序容器都支持push_back。push_back将一个对象(的拷贝而非对象本身)追加到容器的尾部。
vector和string的下标运算符必须在合理范围,不能超过size()的返回值-1。因此,不能用下标向其添加元素。可用push_back添加元素
push_front
list,forward_list,和deque还支持push_front.将元素插入到容器头部
insert
将元素插入到迭代器指定位置之前
对不支持push_front的容器,可用insert(svec.begin(),要插入的元素);将元素插入到容器的开始位置
emplace操作
emplace_front,emplace和emplace_back构造元素,分别将元素放在容器头部,指定位置之前和容器尾部。
这三个函数的参数必须与元素类型的构造函数相匹配
例
vector<string> vs;
vs.emplace_front("hello");
访问容器中的元素
c.front();
c.back();
c[n]
c.at(n)
每个顺序容器都有front(),除forward_list外的所有顺序容器都有back()。at和下标操作只适用于string,vector,deque和array
注意如果容器不是const的,则以上访问成员函数返回的是引用。
注意,不要对空容器调用front和back。调用at和下标操作时,要保证下标不越界。
删除元素
c.pop_back() //删除尾元素,返回void
c.pop_front() //删除首元素,返回void
c.erase(p) //删除迭代器p指向的元素。返回一个指向被删除元素之后元素的迭代器
c.erase(b,e) //删除迭代器范围内的元素。返回指向最后一个被删除元素之后元素的迭代器
c.clear() //删除c中所有元素,返回void
注意,不要对空容器执行pop_back() 和pop_front() 。从容器内部删除元素用erase函数。删除所有元素用clear()
特殊的forward_list操作
在一个forward_list中添加和删除元素的操作是通过改变给定元素之后 的元素完成的。所以,forward_list的操作是在给定迭代器之后添加或删除元素。
例:
lst.insert_after(p,t) //返回指向被插入的元素的迭代器
emplace_after(p,args) //返回指向新元素的迭代器
lst.erase_after(p) //返回指向被删除元素之后元素的迭代器
forward_list还提供了一个函数,获取首元素之前不存在的的元素的迭代器:
lst.before_begin()
容器操作可能使迭代器失效
向vector和string中插入或删除元素时,被插入或删除的元素之前的迭代器,引用和指针仍然有效
对于deque,在首尾添加元素,迭代器会失效,但是指向已存在的元素的引用和指针不会失效。在首尾删除元素,迭代器,指针和引用不受影响(删除尾元素时,只有尾后迭代器器失效)。在其它任何位置添加或删除元素都会造成迭代器、引用和指针失效
对于list和forward_list,添加或删除元素之后,指向容器的迭代器(包括尾后迭代器和首前迭代器)、指针和引用仍有效
如果在一个循环中插入或删除vector,string或deque中的元素,不要缓存end返回 的迭代器,必须在每次操作后都重新调用end函数。
使用插入或删除函数的返回值,可以操作改变后的顺序容器中的元素。
vector管理容量的成员函数
vector和string容器中的元素是连续存储的.当没有空间容纳新的元素时,容器会分配新的空间来保存已有元素和新元素,将已有元素从旧位置移动到新空间中,然后添加新的元素,释放旧空间。每次获取新的空间时,vector和string通常会分配比新的空间需求更大的内存空间。
c.size() //容器已经保存的元素的数目
c.capacity() //容器在不分配新的内存的前提下最多可以保存多少元素
c.reserve(n) //分配至少容纳n个元素的内存空间
c.shrink_to_fit() //将capacity()减少为与size()相同大小
以上函数中,c.shrink_to_fit() 只适用于vector,string和deque.而capacity和reserve只适用于vector和string
注意,当n>c.capacity()时,reserve调用才会改变vector的容量。当n<c.capacity()时,reserve调用什么也不做。
容器适配器
一个容器适配器接受一种类型,使其行为看起来像一种不同的类型
定义适配器
deque<int> deq;
stack<int> stk; //空对象
stack<int> stk2(deq); //用deque对象来初始化一个新的stack
默认情况下,stack和queue是基于deque实现的。priority_queue是在vector之上实现的。也可以重载默认容器类型
vector<string> s(5,"hello");
stack<string, vector<string>> str_stk;
stack<string, vector<string>> str_stk2(s);
stack可以使用除array和forward_list之外的任何一种容器类型来构造。queue可以基于list和queue来构造。priority_queue可以构造于vector和queue.
stack定义在头文件stack中。queue和priority_queue定义在queue头文件中。
stack是后入先出。queue的策略是先进先出。进入队列的被放置到队尾,而离开队列的则从队首删除。
priority_queue中,新加入的元素会排在所有优先级比它低的已有元素之前。调用pop会删除优先级最高的元素。
- c++primer学习笔记 - 容器和算法
- C++学习笔记-容器
- c++Primer学习笔记(6)--抽象容器类型
- C++Primer学习笔记第十章(10/18)关联容器
- c++primer学习笔记 ( 第九章 顺序容器)
- 【C++primer学习笔记】第9章 顺序容器
- 【C++primer学习笔记】第10章 关联容器
- C++Primer学习笔记(9)顺序容器
- C++Primer学习笔记(10)关联容器
- c++primer阅读笔记之关联容器学习
- C/C++进阶学习笔记(二) 容器vector
- C++学习笔记-抽象容器类型
- STL-学习笔记:关联容器
- C++学习笔记-关联容器
- 容器Collection学习笔记
- SpringIOC容器学习笔记
- 学习笔记_容器
- JAVA学习笔记-容器
- android中view创建过程
- Hadoop配置小问题
- Android样式的开发:View Animation篇
- CSDN Code使用图文教程(详细)
- Linux环境下python的tab键补全
- C++学习笔记-容器
- Cocos2d-x Programmers Guide v3.3 译本和阅读笔记(第7章:其他节点类型)
- 我也要做大神
- locust load test
- SpringMVC的配置详解
- kettle从hive取数乱码-问题解决方法(可下载改写驱动)
- 模拟计算器进行四则运算(同等优先级)(第2届第3题)
- 第三十六课 用循环处理文字 【项目1-5】
- WCF之配置文件详解