vector的使用与string的使用是基本一样的,底层是实现上,都是用数组来进行底层的实现,因此,基本的接口使用都几乎无差别,实质上,vector就是一个顺序表。那么vector和string类型有何区别呢?
在实现上,vector是没有‘\0’的,而string有,并且在具体的操作上,也有着不同的区别。而在使用上string一般是存单项信息的。
构造:
vector<int>v1;
vector<int>v2(v1);
vector<int>v3(4,100);//4个整型,值为100
vector<int>v4(v3.begin(),v3.end());
遍历的方式和string一样,而迭代器的使用,也基本是一样的。
vector<int>::iterator it = v3.begin();
while(it != v3.end())
{
cout<<*it<<endl;
it++;
}
范围for也如string一样。
另外三种迭代器
const_iterator
reverse_iterator
const_reverse_iterator
既然是顺序表,就需要增容,一般,在vs上是1.5倍的增容,在g++上,是两倍的增容,增容只是选择,各有利弊,次数多,效率低,空间大,浪费多,所以平衡最重要。
reserve,resize和[]的使用和string没有什么不同,不过vector有个at,at的访问如果失败就会抛出异常。
插入push_back和push_pop,也有insert和erase但是这里要给迭代器。
v.insert(v.begin(),0);
v.erase(v.end());
如果要删除一个确定的值呢,在vector中是没有find的,但是在algorithm,中有find函数在一个左闭右开的区间中,找一个值,sort同样是左闭右开的区间,而他们函数的实现,是模板的泛型编程。
迭代器失效:
一:
vector<int>v;
v.push_back(1);
v.push_back(1);
v.push_back(1);
v.push_back(1);
vector<int>::iterator it = v.begin();
v.push_back(1);
v.push_back(1);
这里是第一种情况,因为扩容,是需要释放原来的空间,并且开辟新空间的,但是迭代器依旧是以前的那空间的指针,那么就会失效。
2:如果要迭代的时候进行删除
while(it != v.end())
{
if(*it % 2 == 0)
{
v.erase(it);
}
++it;
}
因为如果要删除数据,顺序表会将后面的数据挪动到前面去,此时这个it指针所指向的是下一个数据了,如果加加,那么就会越过删除数据的下一个数据的判别。这里vs会严格检查出错误,但是g++中不一定会检查出来,因为严格上只是it指针的意义变了,其实语法上并无错误。
所以如果要防止这种情况,erase有个返回值,返回的是删除的下一个数据的指针,所以我们会这样写
while(it != v.end())
{
if(*it % 2 == 0)
{
it = v.erase(it);
}
else
{
it++;
}
}
这样便可以防止迭代器的失效了。