STL之vector

STL被内建在编译系统之内。STL的版本很多,常见的有HP STL(始祖)、PJ STL(VC++采用)、 SGI STL(GCC采用)等。

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,前者表示容器总共能够存放的元素的容量,后者表示当前已经存储的元素个数(有效元素个数).
vector能自动动态增长.当vector中元素放满后(即capacity等于size时),gcc中它会以原大小两倍配置另一块空间(vs中增长策略有些不同,因此具体capacity的增长行为随着STL的实现版本有所差异),然后把原先内存拷贝到新的空间,并释放原空间.因此在向vector中加入元素时,可能导致原先的所有迭代器都失效.

注意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的输出结果:

STL之vector_第1张图片

VS2012的输出结果:

STL之vector_第2张图片

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;
}

你可能感兴趣的:(STL之vector)