C++ vector 容器浅析:https://www.runoob.com/w3cnote/cpp-vector-container-analysis.html (非常全面)
C++STL容器之Vector详解:https://blog.csdn.net/nilaodie110/article/details/88537555?depth_1-utm_source=distribute.pc_relevant.none-task&utm_source=distribute.pc_relevant.none-task
目录
0vector容器
vector(向量容器)的数据安排以及操作方式,与array非常相似,两者的唯一差别在于空间的运用灵活性,Array是静态空间,一旦配置了就不能改变,要换大一点或者小一点的空间。
vector是动态空间,随着元素的加入,它的内部机制会自动扩充空间以容纳新元素。因此vector的运用对于内存的合理利用与灵活性相较array有很大帮助。
vector会自动调整大小,根据添加元素,自动扩容,下面是示例代码。
vector<int> V;
for(int i = 0;i<10;++i)
{
V.push_back(i);
cout<<V.capacity()<<endl;
}
输出:
并不是单纯的扩大二倍,而是有一套自己的算法。
vector迭代器
器使用一个内存分配器对象来动态地处理它的存储需求。
vector维护一个线性空间,不论元素的类别如何,普通指针都可以作为vector的迭代器
vector<int> :: iterator it1;
vector<Teacher>::iterator it2;
显然it1是int *类型,it2是Teacher *类型
当然,也有const_iterator和reverse_iterator
vector数据结构
vector所采用的数据结构非常简单,线性连续空间,它以两个迭代器_Myfrist和_Mylast分别指向配置得来的连续空间中目前已被使用的范围,并以迭代器_Myend指向整块连续内存空间的尾端
为了降低空间配置时的速度成本,vector实际配置的大小可能比客户端需求大一些,以备将来可能的扩充,这边是容量的概念,
一个vector的容量永远大于或等于其大小,一旦容量等于其大小,就是满栈,下次再有新增元素,整个vector容器就得另觅居所。
所谓的另觅居所,就是要重新找一块内存空间,将目前的所有内容重新拷贝过去,此时,整个vector的首指针要改变指向。(见1.4)
支持对序列中的任意元素进行快速直接访问,甚至可以通过指针算述进行该操作。
操供了在序列末尾相对快速地添加/删除元素的操作。 只能从队尾插入元素
所以可以在API中看到,没有替换API,如果需要在中间插入或替换元素,则比较麻烦。
头文件
using namespace std;
#include<vector>;
1vector常用API介绍
1.1构造函数
vector():创建一个空vector
vector(int nSize):创建一个vector,元素个数为nSize
vector(int nSize,const t& t):创建一个vector,元素个数为nSize,且值均为t
vector(const vector&):复制构造函数
vector(begin,end):复制[begin,end)区间内另一个数组的元素到vector中
操作:
vector<int> V1;
int arr[] = {1,2,3,4,5,6};
vector<int> V2(arr,arr+sizeof(arr)/sizeof(int));
qDebug()<<"V2";
Print(V2);
vector<int>V3(V2.begin(),V2.end());
qDebug()<<"V3";
Print(V3);
vector<int> V4(10,300);
qDebug()<<"V4";
Print(V4);
其中的Print函数会在之后介绍
1.2赋值
void assign(int n,const T& x):设置向量中第n个元素的值为x
void assign(const_iterator first,const_iterator last):向量中[first,last)中元素设置成当前向量元素
具体操作
//赋值
vector<int> V5;
V5.assign(V3.begin(),V3.end());
qDebug()<<"V5";
Print(V5);
1.3交换
void swap(vector&):交换两个同类型向量的数据
具体操作:
//互换
V4.swap(V5);
qDebug()<<"V4";
Print(V4);
qDebug()<<"V5";
Print(V5);
1.4 常用
判断vector内是否为空
bool empty() const:判断向量是否为空,若为空,则向量中无元素
返回大小,容量,最大允许值
int size() const:返回向量中元素的个数
int capacity() const:返回当前向量所能容纳的最大元素值
int max_size() const:返回最大可允许的vector元素数量值
示例:
vector<int>v;
for(int i = 0;i<300;i++)
{
v.push_back(i);
}
qDebug()<<"V的容量"<<v.capacity();
qDebug()<<"V的大小"<<v.size();
v.resize(3);
qDebug()<<"V的容量"<<v.capacity();
qDebug()<<"V的大小"<<v.size();
vector扩容机制:
vector<int>v;
int * p = nullptr;
int num=0;
for(int i = 0;i<300;i++)
{
v.push_back(i);
if(p != &v[0])
{
p = &v[0];
num++;
}
}
qDebug()<<"更换地址次数:"<<num - 1;
解释程序:因为每次扩容,如果原始内存不够,会迁移内容到新的一块更大的内存中去,那么显然首地址的指向也会变好,if判断中的就是当vector扩容后,迁移地址的次数。
但是,当我们知道,vector即将放入300个数据,可以添加如下操作:reserve
vector<int>v;
v.reserve(300);
int * p = nullptr;
int num=0;
for(int i = 0;i<300;i++)
{
v.push_back(i);
if(p != &v[0])
{
p = &v[0];
num++;
}
}
qDebug()<<"更换地址次数:"<<num - 1;
一步到位,不需要其他变更地址的操作,节省空间和时间。
其他常用
at(int i);//访问第i个元素,越界时,抛出out_of_range异常
operator[]//同上,越界时,直接报错
front();//返回容器中的第一个元素
back();//返回容器中的最后一个元素
insert(const_interator pos,int count,ele);//迭代器指向的位置pos插入count个元素ele
push_back(index);//在尾部插入元素index
pop_back();//最后一个元素出队,删除最后一个元素
clear();//清空
erase(const_interator start,const_interator end);//删除迭代器从start到end之间的元素
erase(const_interator pos);//删除迭代器指向的位置的元素
clear();//删除容器中所有元素
1.5迭代器的使用
terator begin():返回向量头指针,指向第一个元素
iterator end():返回向量尾指针,指向向量最后一个元素的下一个位置
reverse_iterator rbegin():反向迭代器,指向最后一个元素
reverse_iterator rend():反向迭代器,指向第一个元素之前的位置
打印(正向遍历)
void Print(vector<int> &V)
{
for(vector<int>::iterator it = V.begin();it!=V.end();++it)
{
qDebug()<<*it<<" ";
}
}
(反向遍历)
void A_Print(vector<int> &V)
{
for(vector<int>::reverse_iterator ti = V.rbegin();ti!=V.rend();++ti)
{
qDebug()<<*ti<<" ";
}
}
此处只是简单的介绍了几种非常常见的vector的API
更加全面的API介绍请移步:
https://www.runoob.com/w3cnote/cpp-vector-container-analysis.html