系统之家装机大师 V1.5.5.1336 官方版
系统之家装机大师是专为小白用户打造的装机工具,操作简单,适合32位和64位的电脑安装使用,支持备份或还原文件,也能通过系统之家装机大师,制作U盘启动盘,智能检测当前配置信息,选择最佳的安装方式,无广告,请大家放心使用。
时间:2015-09-30 16:48:42
发布者:fangfang
来源:当客下载站
三大顺序容器的简单使用与对比
前言:
我们在平时做项目的时候都会接触到容器,而我可能还有很多朋友都没有系统的学习过容器,导致里面很多概念容易混淆,在这里,我简单的总结了顺序容器的简单使用。这篇文章起到在做项目的时候检索的作用,以及三种容器中的不同操作,这是重点。讲述如何去开车,而不是去修车,强调的是使用,而不是讲解,更不是深入讲解。如果大家在看完这个想深入研究容器的话,可以去看深入剖析STL这类专业性更强的丛书。
这篇文章介绍了容器的初始化、迭代器操作、容器内部定义的类型别名、插入元素、容器的比较、元素的访问、删除元素最后以vector容器自增长来结束,希望这些内容对你在工作上有所帮助!
正文:
三大顺序容器:
1. vector -> 支持快速随机访问
2. list -> 支持快速插入和删除
3. deque -> 双端队列
容器的初始化:
C c; 创建一个名为c的空容器。c是容器类型名。
C c(c2); 将c2容器赋值飞c容器。
C c(begin,end); 创建容器c,并用迭代器begin和end之间的元素进行初始化。
C c(n, t); 用n个值t的元素进行初始化。
C c(n); 创建n个值初始化。
这个地方的内容比较简单,就不列举例子了。
容器内元素的约束类型:
大多数类型都可用做容器的元素类型。容器元素类型必须满足两个约束:
1. 元素类型必须支持赋值运算。
2. 元素类型的对象必须可以复制。
这里要注意的是,引用不支持一般意义的赋值运算,所以没有元素是引用类型的容器。io库类型不支持赋值和赋值,所以也不能创建存放io类型对象的容器。
迭代器的操作,以及vector和deque特有的:
迭代器的作用是指向容器中的元素,但也可以指向容器末端的下一位。迭代器类似指针,可以对指向容器元素的迭代器进行解引操作,还可以进行其他操作。
通用如下:
*iter;
iter -> mem;
++iter;
iter++;
--iter;
iter--;
iter1 == iter2;
iter1 != iter2;
下面的迭代器操作是vector与deque特有的,list不可以使用:
iter + n;
iter - n;
iter1 += iter2;
iter1-= iter2;
iter1 - iter2;
<
>
<=
>=
list中迭代器不支持大于小于操作符,所以迭代list的时候不要用iter < li.end()这样的操作,要用iter!=li.end()。
容器内定义的别名:
这是容器自己定义的类型,这个地方没什么好说的,把定义的类型别名做个列举吧。
1. size_type 无符号整形,足以存储迭代器类型最大可能容器长度
2. iterator 此容器类型的迭代器
3. const_iterator 元素的只读迭代器类型
4. reverse_iterator 逆序寻址元素的迭代器
5. const_reverse_iterator 元素只读的逆序迭代器
6. difference_type 足够存储两个迭代器差值的有符号整形,可为负数
7. value_type 元素类型
8. reference 元素左值类型,是value_type&的同义词
9. const_reference 元素常量的左值类型,等效于const value_type&
插入元素:
在顺序容器中添加元素有以下几种方法:
1. c.push_back(t); -> 在容器c的尾部添加值为t的元素。返回void,俗称尾插。
2. c.push_front(t); ->与尾插相反,这个是在c容器的头部添加值为t的元素。返回同样是void,俗称头插,但一定要注意,这种方式只使用与list和deque,而不支持vector,在后面我们也会提到删除,vector也同样不支持头删。
3. c.insert(p,t); -> 在迭代器p所指向的元素前面插入值为t的新元素。返回指向新元素的迭代器。
4. c.insert(p, n, t); -> 在迭代器p所指向的元素前面插入n个值为t的新元素。返回void类型。
5. c.insert(p, begin,end); ->在迭代器p所指向的元素前面插入有迭代器begin和end标记的范围内的元素,返回值同样为void。
注意,想插入,删除这样的操作有可能使迭代器失效,只要是元素的位置发生了变化,那么指向它的迭代器就会失效。
关系操作符,从其大小操作:
关系操作符比较简单,容器都支持关系操作符进行容器的比较,包括<,>,!=等操作,但是一定要注意,连个容器的类型一定要相同。
1. c.size(); -> 返回c容器中元素的个数,返回容器内元素的个数。类型是c::size_type
2. c.max_size(); -> 返回容器c可容纳的最多元素个数
3. c.empty(); -> 返回容器是否为空,为空返回true,否则返回false
4. c.resize(n); -> 调整容器的长度,如多n小于size的话,删除多余的元素,否则初始化多出来的新元素。
5. c.resize(n, t); -> 多出来的新元素用t进行初始化。
访问元素操作:
1. c.back(); -> 访问容器最后一个元素
2. c.front(); -> 访问容器第一个元素
如果容器为空,上述操作未定义。
以下是比较方便的访问操作,但是只适用于vector和deque,list不支持。
3. c[n]; ->访问容器中第n个元素。
4. c.at(n); ->访问容器中第n个元素。
下标越界的话,操作未定义。
删除元素操作:
删除元素很容易理解,即删除容器当中指定的元素。
有以下几个操作:
1. c.erase(p);
删除迭代器p所指向的元素,返回一个被删除元素后面的元素的迭代器。不过要注意p并不是c.end();而是真实存在的元素。
2. c.erase(begin,end);
删除迭代器begin和end范围内容的元素,返回迭代器指向删除段的下一个元素。
3. c.clear();
删除容器全部元素,返回void。
4. c.pop_back();
删除容器中最后一个元素
只适用于list与deque的
c.pop_front();
删除容器中的第一个元素。这里面没有vector的事儿,vector不支持前插与前删。前删除与后删除返回值同样是void,如果容器为空的话,这样的操作未定义。
赋值操作与swap操作:
与赋值相关的操作都将作用于整个容器。功能上理解起来非常简单,就是把左操作数容器的内容全部删除,在将右操作数容器插入到左操作数容器,有以下几种方式。
1. c1 = c2
将c1中的内容清除,将c2中的内容插入到c1中。
2. assign函数
这个函数有两个版本
c.assign(begin,end); 将迭代器begin和end中的元素插入到c中,但是这两个迭代器不能是不能是指向c中元素的迭代器。
c.assign(n, t); 将迭代器重置为n个t元素。
需要注意的是容器的类型一定要相同。操作完成迭代器失效。
swap操作可以节省删除元素的成本。
这个操作是将两个容器的内容互换,所以容器类型要相同。右操作容器中原来的内容放于左操作容器中。由于没有增加删除移动容器的元素,所以迭代器不会失效。
vector容器的自增长:
为什么是涉及到vector容器自增长的问题呢?因为vector容器内的元素在内存中是连续存放的,假如我想在后面加入一个元素,不能随便在内存的其他位置开辟一块空间,于是我们不得不开辟比现有容器更大的空间,然后把以前的容器元素复制到新的空间里,在把新元素加到后面,之后释放掉以前容器占用的空间。这样的话我们每插入一个元素的话只开辟原有vector容器再多一个的空间,这样vector的性能会非常非常的大。另外插一句额外的话,list容器使用的是链表的数据结构,新增加元素不用关心在内存什么位置添加,我只要修改结构里节点中指向下一个节点的指针指向即可。这也是为什么vector的随机访问性能优于list,而随机插入元素的性能低于list。
基于上述的原因,为了提高vector的性能,我们应该在vector添加元素的时候要多开辟一些空间,多开辟多少空间根据库的不同而不同。这里面还涉及一个概念叫做容量,容量是指这个vector容器新分配的存储空间能存放多少个元素。他和容器大小的区别是,大小只是容器装的元素的个数。举个例子,容量就好像是水杯的容量,而容器大小就是里面装的水的体积。所以容量只大于等于容器长度,不能小于。
1. capacity函数,返回容器的容量值。
例子程序:当我们耗尽了容器的容量,在插入才进行内存分配。因此是必要的时候才重新分配内存空间。
2. reserve函数,手动设置vector容器应该预留多大的容量。