标准库负责内存的管理,程序猿关注实际需要解决的问题。
泛型算法:用于不同的容器类型,容器又可以容纳多种不同类型的元素。
容器类型提供通用接口。
顺序容器:单一类型元素聚集成为容器,根据位置来存储和访问。
顺序容器 |
vector 支持快速随机访问 |
list 支持快速插入/删除 |
deque 双端队列 |
顺序容器的适配器 |
stack 后进先出LIFO栈 |
queue 先进先出FIFO队列 |
priority_queue 优先级管理的队列 |
顺序容器的头文件
#include<vector>
#include<list>
#include<deque>
所有容器都是类模板;两个类型---容器类型和元素类型
list<string> slist(vec.begin(),vec.end());
vector<string>::iterator mid = vec.begin() + vec.size()/2;
deque<string> front(vec.begin(),mid);
//不包含*mid元素
(1)元素类型必须支持赋值运算;
(2)元素类型的对象必须可以复制。(引用类型不行,不支持一般意义上的赋值)
IO库类型不支持复制或赋值,所以不能创建IO类型对象的容器。
容器的容器
vector< vector<string> > lines;
注意:空格必不可少。
关系操作符只适用于vector和deque容器;
list容器的迭代器既不支持算术运算,也不支持关系运算,只用前置和后置的自增和自减以及相等(不等)运算。
size_type 存储此容器类型的最大可能容器长度 |
---|
iterator 此容器类型的迭代器,是容器类的成员 |
const_iterator 元素的只读迭代器类型 |
reverse_iterator 按逆序寻址元素的迭代器 |
difference_type 足够存储两个迭代器的有符号差值 |
value_type 元素类型 |
reference 元素的左值类型,value_type&的同义词 |
const_reference 等效于cosnt value_type& |
const_reverse_iterator 元素的只读(不能写)逆序迭代器 |
c.push_back(t)容器尾部添加值为t的元素,返回void类型 |
---|
c.push_front(t) 容器前端添加值为t的元素,返回void类型 (适用于list和deque) |
c.insert(p,t) 迭代器p指向元素的前面插入值为t的新元素,返回指向新元素的迭代器 |
c.insert(p,n,t) 同上,插入n个值为t的新元素,返回void |
c.insert(p,b,e) 同上,插入迭代器b和迭代器e标记的范围内的元素,返回void |
迭代器范围:编译器无法知道迭代器所关联的哪个容器
迭代器失效问题
vector<int>::iterator first = v.begin(),
end = v.end();
while(first != end){
first = v.insert(first,42);
++first;
}
while(first != end){
first = v.insert(++first, 42);
++first;
}
对比两个程序段,上一个迭代器已经失效,会导致灾难性后果,第二个中++first很重要,保证数据前后顺序是先插入的在前
c.size( ) 返回类型是c::size_type |
c.max_size( ) 返回类型是c::size_type |
c.empty( ) 容器为空,返回1 |
c.resize( ) n< c.size( ),删除多余的元素; 否则,添加采用值初始化的新元素 |
c.resize(n, t) 添加新元素的值是t |
c.back( ) 返回最后一个元素的引用,如c为空,该操作没有定义 |
c.front( ) 返回第一个元素的引用,如c为空,该操作没有定义 |
c[n] 返回引用,如有 n < 0 或 n > c.size( ),操作无定义,只适用于vector和deque容器 |
c.at(n) 返回引用,越界则操作无定义,只适用于vector和deque容器 |
c.erase(p) 删除迭代器p指向的元素,返回删除元素的后一个迭代器,p本身指向末端下一位置,操作无定义 |
c.erase(b,e) 删除迭代器b和e范围内元素,返回迭代器指向删除后面的元素,e本身指向末端下一位置,则返回的迭代器也指向容器超出末端的下一位置 |
c.clear( ) 删除容器的所有元素,返回void |
c.pop_back( ) 删除容器c的最后一个元素,返回void。c为空,操作无定义 |
c.pop_front( ) 删除容器c的第一个元素,返回void。 c为空,操作无定义 只适用于list和deque |
代码范例:
while(!ilist.empty()){
process(ilist.front());
ilist.pop_front();
}
erase函数不会检查它的参数,所以程序猿必须保证做参数的迭代器或迭代器范围是有效的
使用erase函数的保险做法:
#include<algorithm>
string searchValue("QQ");
list<string>::iterator iter = find(slist.begin(),slist.end(),searchValue);
if(iter != slist.end())
slist.erase(iter);
find函数查找完成后,该函数返回一个迭代器,指向指定值的第一个元素,或超出末端的下一个位置
c1 = c2 c1和c2的类型(容器类型和元素类型)必须相同 |
c1.swap(c2) 函数执行速度比c2元素复制到c1快 |
c.assign(b,e) 迭代器b和e标记的范围所有元素复制到c中,b和e必须不是指向c的迭代器 |
c.assign(n,t) 将容器c重置为存储n个值为t的元素 |
如果在不同类型的容器内,元素类型不同但是兼容,其赋值操作就必须使用assign函数。
assign函数首先删除容器中的所有元素,然后将参数所指定的新元素插入到该容器中。
vector容器的capacity和reserve成员
capacity: 获取在容器需要分配更多的存储空间之前能够存储的元素总数
reserve:告诉vector应该预留多少个元素的存储空间(或者更多的存储空间)
注意:
vector的每种实现都可自由的选择自己内存分配策略。然而,都必须提供
capacity和reserve函数,而且是在必要时分配新的内存空间。不同库采用的策
略不同。