STL学习记录(四):Vector

STL顺序容器Vector

Vector简介

Vector 容器就像传统C语言里的动态数组一样。Vector将它的所有元素都复制到它内部的动态数组中。这些元素具有一定的相对顺序。所以,vector容器是顺序容器,它支持随机方式访问容器里面的元素。这样你就可以通过迭代器在一个常数的时间里访问到该元素。它的迭代器是随机访问迭代器,因此能够使用STL里面的每一个标准算法。Vector容器在末尾进行插入删除的效率很高,但是在中间进行插入删除操作则效率低下,因为在中间插入删除,就要对插入或者删除位置之后的元素位置进行相应的调整,极端情况下需要移动整个容器里面的元素。

Vector基本操作

size and capacity

Vector表现良好的一个原因就是它总是分配足够多的内存来让你存放元素。为了更好、更准确的使用vector,我们需要理解它的size和capacity操作。size()返回vector当前的大小,capacity()返回下次再分配内存空间时所需要的最少元素个数,当元素个数超过capacity后vector会再次capaticy分配空间(分配空间大小与编译器有关Linux采用是翻倍,VS采用的策略不是这样)。

非修改性操作:

操作说明
c.enpty()判断容器是否为空,为空返回true
c.size()返回当前容器内元素数量
c.max_size()返回容器可能保存的最多元素
c.capavity()返回在下次再分配空间时所能存放元素的最大数量
c.reserve(num)当空间不够是的时候对capacity进行扩容
c.shrink_to_fit()将apacity的大小重置为元素的数量(c++11)
c1==c2判断c1与c2是否相等
c1!=c2判断c1与c2是否不等
c1>c2判断c1是否大于c2
c1判断c1是否小于c2
c1>=c2判断c1是否大于等于c2
c1<=c2判断c1是否小于等于c2

代码示例:

#include <iostream>
#include <vector>
using namespace std;

int main() {
vector<int> vec;
for(int i=0;i<20;i++) {
    vec.push_back(i);
    cout<<"now capacity is :"<<vec.capacity()<<endl;
}
cout<<"vec size is :"<<vec.size()<<endl;
cout<<"vec maxsize is :"<<vec.max_size()<<endl;

vec.erase(vec.begin()+10,vec.end());
cout<<"after erase vec size is :"<<vec.size()<<endl;
cout<<"after erase capacity is :"<<vec.capacity()<<endl;

//演示c++11中的shrink_to_fit()
vector<int>(vec).swap(vec);
cout<<"after swap vec size is :"<<vec.size()<<endl;
cout<<"after swap capacity is :"<<vec.capacity()<<endl;

for(int i=10;i<20;i++){
    vec.push_back(i);
    cout<<"now capacity is :"<<vec.capacity()<<endl;
}
vec.erase(vec.begin()+10,vec.end());
vec.shrink_to_fit();
cout<<"after shrink vec size is :"<<vec.size()<<endl;
cout<<"after shrink capacity is :"<<vec.capacity()<<endl;

return 0;
}

输出如下(Linux下):
now capacity is :1
now capacity is :2
now capacity is :4
now capacity is :4
now capacity is :8
now capacity is :8
now capacity is :8
now capacity is :8
now capacity is :16
now capacity is :16
now capacity is :16
now capacity is :16
now capacity is :16
now capacity is :16
now capacity is :16
now capacity is :16
now capacity is :32
now capacity is :32
now capacity is :32
now capacity is :32
vec size is :20
vec maxsize is :4611686018427387903
after erase vec size is :10
after erase capacity is :32
after swap vec size is :10
after swap capacity is :10
now capacity is :20
now capacity is :20
now capacity is :20

赋值操作

操作说明
c = c2将c2的所有元素赋值给c1
c = rv将右值rv的所有元素的值移动赋值给c(c++11标准)
c = {x1,x2,x3}使用初始化列表的所有元素赋值给c
c.assign(n , x)用元素x的n个拷贝来初始化c
c.assign(beg , end)用范围[beg,end)内的元素进行赋值
c.assign( {x1,x2,x3} )用初始列表来赋值
c1.swap(c2)交换c1与c2中的数据
swap(c1 ,c2)交换c1与c2中的数据

元素访问操作

操作说明
c[index]返回位于index 位置的元素(不进行范围检查)
c.at(index)返回位于index 位置的元素(进行范围检查,超出范围抛出异常)
c.front()返回第一个元素(不检查该元素是否存在)
c.back()返回最后一个元素(不检查该元素是否存在)

迭代器

操作说明
c.begin()返回指向第一个元素的iterator
c.end()返回指向最后一个元素的iterator
c.cbegin()返回指向第一个元素的const_iterator
c.cend()返回指向最后一个元素const_iterator
c.rbegin()返回指向逆序第一个元素的iterator
c.rend()返回指向逆序最后一个元素的itreator
c.crbegin()返回指向逆序第一个元素的const_iterator
c.crend()返回指向逆序最后一个元素的const_iterator

插入、移除等元素修改操作

操作说明
c.push_back(x )追加x的拷贝到容器的末尾
c.pop_back()直接移除容器内的最后一个元素,不反复其值
c.insert(pos, x )pos 所指位置之前插入元素 x 的副本
c.insert(pos,n,x )pos 所指位置之前插入元素xn 个副本
c.insert(pos,begin,end)pos 所指位置之前插入范围 [begin,end) 所有元素的副本
c.insert(pos, {x1,x2,x3})pos 所指位置之前插入初始话列表中元素的副本(c++11)
c.emplace(pos,args…)插入一个新元素,元素通过使用args… 作为参数传递给默认构造函数构造(c++1)
c.emplace_back(args…)在容器末尾插入一个新元素,元素通过使用args… 作为参数传递给默认构造函数构造(c++11)
c.erase(pos)移除迭代器pos所指元素,并且返回下一个元素的迭代器
c.erase(begin,end)移除范围[begin,end) 之间的所有元素
c.resize(num)改变容器的大小,当增大时新增区域元素采用默认构造函数构造
c.resize(numx)改变容器的大小,当增大时新增区域元素为x 的副本
c.clear()移除所有元素

某些元素访问和元素移除操作中,操作本身是不会进行范围检查的。因此我们在写程序的时候对于这些操作一定要事先进行进行判断,确保操作在合法的范围内进行的。
例如:

std::vector<int> vec;
vec.pop_back();
//这个操作会是未定义行为,会导致运行时错误
//正确的做法
if(!vec.end()) {
    vec.pop_back();
}
//还有一个需要注意的是在进行pop_back()前对vec进行的修改
//例如本来vec有一个元素但是在pop_back()之前,你执行erase()操作已经将它删除,所以每一次删除元素的操作前都要检查范围

vector并没有提供直接删除某个特定值元素的操作,如果你需要相应操作可以参考:

//删除所有值为val的元素
std::vector<int> vec;
vec.erase(remove(vec.begin(),vec.end(),val),vec.end());
//删除第一个值为val的元素
std::vector<int>::iterator pos;
pos=find(vec.begin(),vec.end(),val);
if(pos!=vec.end()) {
    vec.erase(pos);
}

一些操作实例

#include <iostream>
#include <vector>
#include <string>
#include <algorithm>
#include <iterator>
using namespace std;
int main()
{
    vector<string> vec;
    vec.reserve(5);
    vec.push_back("hello,");
    vec.insert(vec.end(),{"how","are","you","?"});
    cout<<"capacity:"<<vec.capacity()<<endl;    
    copy(vec.cbegin(),vec.cend(),ostream_iterator<string>(cout," "));
    cout<<endl;

    swap(vec[1],vec[3]);
    vec.insert(find(vec.begin(),vec.end(),"?"),"always");
    vec.back()="!";

    copy(vec.cbegin(),vec.cend(),ostream_iterator<string>(cout," "));
        cout<<endl;

    cout<<"size:"<<vec.size()<<endl;
    cout<<"capacity:"<<vec.capacity()<<endl;    
    return 0;
}

输出结果
capacity:5
hello, how are you ?
hello, you are how always !
size:6
capacity:10

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值