STL可分为容器(containers)、算法(algorithms)、迭代器(iterators)、空间配置器(allocator)、适配器(adaptors)、仿函数(functors)六个部分。
容器分为序列式容器(primer上翻译为顺序容器)和关联式容器两类.
序列式容器有三种:
vector:支持快速随机访问
list:支持快速插入/删除
deque:双端队列
序列容器适配器三种:
stack:后进先出(LIFO)栈
queue:先进先出(FIFO)队列
priority_queue:优先级队列
vector的存储空间是一段连续内存,支持随机存取,内部主要由3个数据成员来实现:start(目前使用空间的头)、finish(目前使用空间的尾)、end_of_storage(整块连续空间(含备用空间)的尾部).
vector两个容易混淆的方法capacity和size,前者表示容器总共能够存放的元素的容量,后者表示当前已经存储的元素个数(有效元素个数).注意reserve和resize的差别
reserve函数可以增大capacity(注意不能减小capacity),resize可以增大或减小size
reserve(n):当n<capacity时不会起作用,n>capacity时,会使得capacity=n,一般用于初始化vector时指定一个较合适的容量,避免因动态增长影响效率.
resize(n):使得size=n,当n<size时会把后面多余的元素删除掉,n>size时,会加入指定初值的元素,不指定时加入默认值,如int则加入0,若为对象则调用其默认构造函数
调用vector的clear方法时,实际并不释放其空间,可采用swap函数来释放
#include<iostream> #include<vector> using namespace std; void printV(const vector<int> &v)//以引用传递,防止调用拷贝构造产生大开销 { cout<<"size:"<<v.size()<<endl; cout<<"capacity:"<<v.capacity()<<endl; } int main() { vector<int> v; for(int i=0;i<10;++i) { v.push_back(i);//size是有效元素的个数,区别于capacity printV(v);//vector的capacity从自动增长,具体增长策略不同的STL实现版本会不一样! } cout<<"----------reserve(5)-----------"<<endl; v.reserve(5);//reserve参数小于capacity时不会起作用 printV(v); cout<<"----------reserve(20)-----------"<<endl; v.reserve(20);//reserve参数大于capacity时只会改成capacity不改变size printV(v); cout<<"----------resize(3)-----------"<<endl; v.resize(3);//resize参数小于size时会删除多余的元素,减小size printV(v); cout<<"----------resize(6)-----------"<<endl; v.resize(6);//resize参数大于size时会加入指定初值的元素,不指定则加入默认值,并增加size for(vector<int>::iterator it=v.begin();it!=v.end();++it) cout<<*it<<endl;//加入了int的元素默认值是0 printV(v); cout<<"---------swap--tmp----------"<<endl; { vector<int> tmp(v);//使用vector的拷贝构造,注意tmp的size和capacity均等于原先v的size v.swap(tmp);//和tmp进行交换,放在{}可使得tmp自动被析构后回收内存 } printV(v); cout<<"----------clear-------------"<<endl; v.clear();//调用clear只使size清零,但内存并未真正释放,故capacity仍不变 printV(v); cout<<"---------swap--empty--------"<<endl; vector<int>().swap(v);//和空的vector进行交换,此时内存被释放,capacity也归0 printV(v); return 0; }
gcc和vs2012在capacity增长策略上实现不同,其他操作均一致.
gcc的输出结果:
VS2012的输出结果:
vector在遍历元素的时候删除元素的方式
由于删除元素后会导致该元素后面的元素均前移,故该元素之后的所有迭代器均会失效,以下分别是不正确的删除方式和正确的删除方式:
#include<iostream> #include<vector> using namespace std; int main() { vector<int> v; for(int i=0;i<10;++i) v.push_back(i); for(vector<int>::iterator it=v.begin();it!=v.end();++it) { if(*it>=5 && *it<=8)//假设要删除5-8这几个元素 v.erase(it); } for(vector<int>::iterator it=v.begin();it!=v.end();++it) cout<<*it<<endl; return 0; }结果只删除了5和7.
正确的删除方式:
#include<iostream> #include<vector> using namespace std; int main() { vector<int> v; for(int i=0;i<10;++i) v.push_back(i); for(vector<int>::iterator it=v.begin();it!=v.end();/*null*/) { if(*it>=5 && *it<=8) it=v.erase(it);//把返回值赋给it,且不对it自增 else ++it; } for(vector<int>::iterator it=v.begin();it!=v.end();++it) cout<<*it<<endl; return 0; }