1,顺序容器概述
vector | 可变大小数组;支持随机访问。尾部之外插入或删除数据可能很慢。 vector<变量> 名称; 使用:名称[]。 |
---|---|
deque | 双端队列;支持快速随机访问。在头尾位置插入/删除很快。 |
list | 双向链表。不支持随机访问;只支持双向顺序访问;在list中任何位置进行插入/删除速度很快。 |
forward_list | 单向链表。不支持随机访问;在链表中任何位置进行插入/删除速度很快。 |
array | 固定大小数组。不能添加删除元素。 |
vector,deque可以通过下标快速访问,但是增添或减少会耗费大量的代价。
list ,forward_list不支持快速访问,他访问元素必须遍历所有元素。但是增添或减少会更加方便。
选择容器原则:
尽量使用vector;
如果需要在容器中间插入或删除元素,则选择list或者forward_list。
如果不确定使用哪种容器,则可以再程序中只使用vector和list的公共操作:使用迭代器,不使用下标避免随机访问
#include <iostream>
#include <vector>
using namespace std;
int main()
{
vector<int> v; //v是存放int类型变量的可变长数组,开始时没有元素
for (int n = 0; n<5; ++n)
v.push_back(n); //push_back成员函数在vector容器尾部添加一个元素
vector<int>::iterator i; //定义正向迭代器
for (i = v.begin(); i != v.end(); ++i) { //用迭代器遍历容器
cout << *i << " "; //*i 就是迭代器i指向的元素
*i *= 2; //每个元素变为原来的2倍
}
cout << endl;
//用反向迭代器遍历容器
for (vector<int>::reverse_iterator j = v.rbegin(); j != v.rend(); ++j)
cout << *j << " ";
return 0;
}
程序的输出结果是:
0 1 2 3 4
8 6 4 2 0
后置++要多生成一个局部对象 tmp,因此执行速度比前置的慢。同理,迭代器是一个对象,STL 在重载迭代器的++运算符时,后置形式也比前置形式慢。在次数很多的循环中,++i和i++可能就会造成运行时间上可观的差别了。因此,本教程在前面特别提到,对循环控制变量i,要养成写++i、不写i++的习惯。
vector::iterator i; //定义正向迭代器
vector::reverse_iterator j;//用反向迭代器遍历容器
const_reverse_iterator;不能修改元素的迭代器
2,容器操作:通过迭代器做传输作用(就看做读取其内存地址去使用,不涉及其元素本身)
类型别名 | 作用 |
---|---|
iterator | 迭代器类型 |
const_iterator | 可以读取元素,但不能修改元素迭代器类型 |
value_type | 元素类型 |
size() | 元素数目(不支持forward_list) |
empty() | 是否为空 |
clear() | 清空所有元素 |
begin()end() | 指向首元素和尾元素之后位置的迭代器 |
cbegin(),cend() | 返回const_iterator;对于只读不改变元素的算法尽量使用这个 |
加上作用域运算符(:😃 例如:list::iterator iter;
iterator:此容器类型的迭代器类型
const_iterator:不能修改元素迭代器类型
value_type:元素类型
容器类型:容器<类型名>::类型别名 变量名称(也可以称为迭代器)
类型别名可以看做是个类型。
我们可以通过变量名称来使用其成员,成员通过(begin 和end)来实现其值的改变。
例如:list::iterator iter;
iter.begin() , iter.end();
++begin;
1)容器拷贝:
为了创建一个容器为另一个容器拷贝,2个容器类型及其元素类型必须匹配。
当传递迭代器参数来拷贝一个范围时,就不用了考虑容器类型了。
list<string>a1={"c","b"};
vector<int>a2={1,2};
list<string> b1(a1);//正确
deque<string>b2(a1)//错误
vector<string>b3(a2)//错误 元素类型不匹配
vector<int>b4(a1.begin(),a1.end());//正确
b4容器必须和范围中的元素数目一致,新容器的每个元素都用范围中对应元素的值进行初始化。
假设it为a1中的某个元素
vector<int>b4(a1.begin(),it)
2)顺序容器增加操作
c.push_back(t) | 在尾部创建一个值为t的元素 |
---|---|
c.push_front(t) | 在头部创建一个值为t的元素 |
c.insert(p,t) | 在迭代器p指向的元素之前创建一个值为t的元素 |
c.insert(p,n,t) | 在迭代器p指向的元素之前创建n个值为t的元素 |
重要提示:在vector string,deque插入元素会使指向容器的迭代器、引用、和指针失效
3)访问元素
at() | 只适用vector、string、deque、array |
---|---|
c[] | 同上 |
back() | 返回尾元素的引用,不适用forward_list |
front() | 首元素的引用。 |
4)删除元素
这些操作会改变容器大小,所以不适合array
pop_back() | 删除尾元素 |
---|---|
pop_front() | 删除头元素 |
clear() | 清空元素 |
删除deque中除首尾位置之外的任何元素都会使所有迭代器、引用、指针失效。指向vector、string中删除点之后位置的迭代器、引用、指针都会失效
删除元素的成员函数并不会检查其参数。再删除元素之前,程序员必须确保其存在。
5)容器操作可能会使迭代器失效
向容器内添加元素:
如果容器是vector、string,且存储空间被重新分配,则指向容器的迭代器、引用、指针都会失效
对于deque,插入除首尾位置之外的任何元素都会使所有迭代器、引用、指针失效。如果在首尾位置添加元素,迭代器会失效,引用、指针不会失效。删除元素
对于deque,删除deque中除首尾位置之外的任何元素都会使所有迭代器、引用、指针失效。如果删除首元素,不影响。如果删除尾元素,则尾后迭代器会影响,但是其他迭代器、指针、引用不受影响
对于vector、string:指向vector、string中删除点之后位置的迭代器、引用、指针都会失效。指向之前的不受影响。
建议:
当你使用迭代器,最小化要求迭代器必须保持有效性。
由于向迭代器增添或者删除可能会使迭代器失效,所以必须保证每次改变容器大小都重新正确的定义迭代器。对于vector、deque、string尤为重要。
注意看c++primer的355页的2段代码。
3.vector对象是如何增长的
www.baidu.com
所有都是手敲的,老铁给个赞。我也会持续更新有关c++11的一切。