1、vector概述
vector的数据安排以及操作方式与array非常相似。两者的唯一差别在于空间运用的灵活性。array是静态空间,一旦配置了就不能改变。当要扩大空间时,首先要配置新空间,然后将数据转移,还要释放旧空间。vector是动态空间,随着元素的加入,它的内部机制会自行扩充空间以容纳新元素。因此,vector的运用对于内存的合理利用与运用的灵活性有很大的帮助。
2、vector迭代器
vector维护的是一个连续性空间,所以不论其元素型别为何,普通指针都可以作为vector的迭代器而满足所有必要条件,因为vector迭代器所需要的操作行为,如:operator*、operator->、operator++、operator–、operator+、operator-、operator+=、operator-=。vector支持随机存取,而普通指针正有着这样的能力,所以vector提供的是Random Access Iterators(原生态指针),即所存储元素类型的指针。如下所示:
template<class T, class Alloc = alloc>
class vector
{
public:
typedef T value_type;
typedef value_type* iterator; //vector的迭代器是普通指针
...
};
根据上述定义,如果客户端写出这样的代码:
vector::iterator ivite;
vector::iterator svite;
那么:ivite的型别其实就是int*,svite的型别其实就是shape*。
3、vector的数据结构
vector所采用的数据结构非常简单:线性连续空间。它以两个迭代器start和finish分别指向配置得来的连续空间中目前已被使用的范围,并以迭代器end_of_storage指向整块连续空间(含备用空间)的尾部,如下所示:
template<class T, class Alloc = alloc>
class vector
{
...
protected:
iterator start; //表示目前使用空间的头
iterator finish; //表示目前使用空间的尾
iterator end_of_storage; //表示目前可用空间的尾
...
};
释:为了降低空间配置时的速度成本,vector实际配置的大小可能比客户端需求量更大一些,以备将来可能的扩充,这便是容量的观念。换句话说,一个vector的容量永远大于或等于其大小。一旦容量等于大小,便是满载,下次再有新增元素,整个vector就得另觅居所。运用start、finish、end_of_storage三个迭代器,便可轻易地提供首尾标识、大小、容量、空容器判断、标注([ ])运算子、最前端元素值、最后端元素值等机能,如下图所示。
其中,部分元素的定义如下所示:
template<class T, class Alloc = alloc>
class vector
{
...
public:
iterator begin()
{
return start;
}
iterator end()
{
return finish;
}
size_type size()const
{
return size_type(end() - begin());
}
size_type capacity()const
{
return size_type(end_of_storage - begin());
}
bool empty()const
{
return begin() == end();
}
reference operator[](size_type n)
{
return *(begin() + n);
}
reference front()
{
return *begin();
}
reference back()
{
return *(end() - 1);
}
...
};
4、vector的构造与内存管理
所谓动态增加大小,并不是在原空间之后接续新空间,因为无法保证原空间之后尚有可供配置的空间,而是以原大小的两倍另外配置一块较大空间,然后将原内存内容拷贝过来,接着才开始在原内容之后构造新空间,并释放原空间。因此,对vector的任何操作,一旦引起空间重新配置,指向原vector的所有迭代器就都失效。
1)allocate_and_fill(size_type, const T& x):配置后填充
2)fill_initialize(size_typen, const T& value):填充并予以初始化。
5、vector的元素操作
使用vector时必须包含vector头文件:必须引入标准命名空间std。
(1)vector的成员函数,访问权限是protected。
1)start:表示目前使用空间的头;
2)finish:表示目前使用空间的尾;
3)end_of_storage:表示目前可用空间的尾;
4)insert_aux(iterator position, const T& x):在position位置插入一个n数值;
5)deallocate:销毁和释放vector的整个空间;
6)fill_initialize(size_typen, const T& value):填充n个元素,并初始化为value数值。
(2)vector的成员函数,访问权限是public。
1)begin():vector有效元素的首端。
2)end():vector有效元素的尾端。
3)size():获取vector中有效元素的个数。
4)resize():更改vector中有效元素的个数。
5)capacity():获取空间大小。
6)empty():检测是否为空。
7)reserve():改变容量的空间,但是不改变有效元素的个数。
8)front():vector有效元素的第一个元素,返回*begin()
9)back():vector有效元素的最后一个元素的前一个元素,返回end()-1。
(3)全局函数
1)push_back(n):将元素n插入到最后端。
2)pop_back():将最尾端元素取出。
3)erase():清除任意位置上的元素。
4)destroy():销毁。
5)insert(iterator position, size_type n, const T& x):在position位置插入n个x。
6)clear():将vector中的元素清空,不改变容量。
7)assign():赋值。
8)allocate_and_fill:配置空间并填满内容
9)uninitialized_fill_n
10)operator[]:随机访问。
11)resize:更改vector中有效元素的个数。
6、实例
【例1】
#include<vector>
#include<stdlib.h>
#include<iostream>
using namespace std;
void TestVector1()
{
//构造一个空的vector
vector<int> v1;
//构造一个空的vector,但是底层空间大小设置为20个元素
vector<int> v2(20);
//构造一个vector对象,并用数组进行初始化
int array[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
vector<int> v3(array, array + sizeof(array) / sizeof(array[0]));
//查看v1中元素的个数
cout << "v1是一个空的vector" << endl;
cout << "size1 =" << v1.size() << endl;
//查看v1容量的大小
cout << "capacity1 =" << v1.capacity() << endl << endl;
cout << "v2是一个空的vector,但是底层空间大小设置为20个元素" << endl;
cout << "size2 =" << v2.size() << endl;
cout << "capacity2 =" << v2.capacity() << endl << endl;
cout << "v3是初始化为0到9的vector" << endl;
cout << "size3 =" << v3.size() << endl;
cout << "capacity3 =" << v3.capacity() << endl << endl;
//将v3赋值给v1后再次查看v1的元素个数和容量大小
cout << "将v3赋值给v1后再次查看v1的元素个数和容量大小" << endl;
v1 = v3;
cout << "size1 =" << v1.size() << endl;
cout << "capacity1 =" << v1.capacity() << endl;
cout << "v1 data:";
for (size_t i = 0; i < v1.size(); i++)
{
cout << v1[i] << " ";
}
cout << endl;
cout << "v3 data:";
for (size_t i = 0; i < v1.size(); i++)
{
cout << v1[i] << " ";
}
cout << endl << endl;
//将v3赋值给v2后再次查看v2的元素个数和容量大小
cout << "将v3赋值给v2后再次查看v2的元素个数和容量大小" << endl;
v2 = v3;
cout << "size2 =" << v2.size() << endl;
cout << "capacity2 =" << v2.capacity() << endl;
cout << "v2 data:";
for (size_t i = 0; i < v1.size(); i++)
{
cout << v2[i] << " ";
}
cout << endl;
cout << "v3 data:";
for (size_t i = 0; i < v1.size(); i++)
{
cout << v1[i] << " ";
}
cout << endl << endl;
//将v2赋值给v3后再次查看v3的元素个数和容量大小
cout << "将v2赋值给v3后再次查看v3的元素个数和容量大小" << endl;
v3 = v2;
cout << "size3 =" << v3.size() << endl;
cout << "capacity3 =" << v3.capacity() << endl;
cout << "v3 data:";
for (size_t i = 0; i < v3.size(); i++)
{
cout << v3[i] << " ";
}
cout << endl;
cout << "v2 data:";
for (size_t i = 0; i < v2.size(); i++)
{
cout << v2[i] << " ";
}
cout << endl;
//注意:除了该函数的作用域之后,vector会自动将其内部的空间释放掉
}
int main()
{
TestVector1();
system("pause");
return 0;
}
运行结果为:
【例2】push_back/pop_back/insert/erase
void TestVector2()
{
//构造一个空的vector,然后向里面尾插入1、2、3、4、5,5个元素
vector<int> v2;
v2.push_back(1);
v2.push_back(2);
v2.push_back(3);
v2.push_back(4);
v2.push_back(5);
cout << "尾插入5个元素后:" << endl;
cout << "size =" << v2.size() << endl;
cout << "capacity =" << v2.capacity() << endl;
//打印vector中的元素
cout << "v2 data:";
for (size_t i = 0; i < v2.size(); i++)
{
cout << v2[i] << " ";
}
cout << endl << endl;
//尾删
v2.pop_back();
v2.pop_back();
cout << "尾删2个元素后" << endl;
cout << "size =" << v2.size() << endl;
cout << "capacity =" << v2.capacity() << endl;
cout << "v2 data:";
for (size_t i = 0; i < v2.size(); i++)
{
cout << v2[i] << " ";
}
cout << endl << endl;
//insert——任意位置插入
cout << "在vector起始位置插入数据0后:" << endl;
v2.insert(v2.begin(), 0);
cout << "size =" << v2.size() << endl;
cout << "capacity =" << v2.capacity() << endl;
cout << "v2 data:";
vector<int>::iterator it = v2.begin();
while (it != v2.end())
{
cout << *it++ << " ";
}
cout << endl << endl;
cout << "在vector末尾位置插入2个8后:" << endl;
v2.insert(v2.end(), 2, 8);
cout << "size =" << v2.size() << endl;
cout << "capacity =" << v2.capacity() << endl;
cout << "v2 data:";
for (size_t i = 0; i < v2.size(); i++)
{
cout << v2.at(i) << " ";
}
cout << endl << endl;
//删除任意位置元素
v2.erase(v2.begin()); //删除起始位置
v2.erase(v2.begin(), v2.begin() + 2);//删除指定区间内的元素,注意区间是“[)”
//使用vector迭代器遍历vector中所有元素
it = v2.begin();
cout << "删除起始位置元素和指定区间内元素后:" << endl;
cout << "v2 data:";
while (it != v2.end())
{
cout << *it++ << " ";
}
cout << endl;
}
运行结果为:
注意:
1)如果用迭代器vector代替for语句,会出错。因为:当插入新元素,内存不足时,系统会开辟新的空间,然后把原来的数据复制到新空间里,最后把原来的空间释放掉。
2)vector底层为连续空间,支持随机访问,vector重载了[]。
【例3】//assign/resize/clear
void TestVector3()
{
vector<int> v3;
v3.push_back(1);
v3.push_back(2);
v3.push_back(3);
v3.push_back(4);
v3.push_back(5);
v3.push_back(6);
cout << "v3 data:";
for(size_t i = 0; i < v3.size(); ++i )
{
cout << v3[i] << " ";
}
cout << endl;
//给vector中5个值为8 的元素
v3.assign(5, 8);
cout << "给vector中5个值为8的元素后,v3 data:";
for(size_t i = 0; i < v3.size(); i++)
{
cout << v3[i] << " ";
}
cout << endl;
cout << "size =" << v3.size() << endl;
cout << "capacity =" << v3.capacity() << endl;
//将vector中元素清空,注意底层容量的空间不变
v3.clear();
cout << "将vector中元素清空后,v3 data:";
for(size_t i = 0; i < v3.size(); i++)
{
cout << v3[i] << " ";
}
cout << endl;
cout << "size =" << v3.size() << endl;
cout << "capacity =" << v3.capacity() << endl;
//将vector中的元素增加到3个
v3.resize(3);
cout << "将vector中元素增加到3个后,v3 data:";
for(size_t i = 0; i < v3.size(); i++)
{
cout << v3[i] << " ";
}
cout << endl;
cout << "size =" << v3.size() << endl;
cout << "capacity =" << v3.capacity() << endl;
//将vector中的元素增加到10个
v3.resize(10);
cout << "将vector中的元素增加到10个后,v3 data:";
for(size_t i = 0; i < v3.size(); i++)
{
cout << v3[i] << " ";
}
cout << endl;
cout << "size =" << v3.size() << endl;
cout << "capacity =" << v3.capacity() << endl;
//将vector底层容量空间增加到20个
v3.reserve(20);
cout << "将vector底层容量空间增加到20个后,v3 data:";
for(size_t i = 0; i < v3.size(); i++)
{
cout << v3[i] << " ";
}
cout << endl;
cout << "size =" << v3.size() << endl;
cout << "capacity =" << v3.capacity() << endl;
}
运行结果为:
注意:
(1)assign()是给vector进行赋值,在赋值之前,该方法会先将vector中原有的旧元素erase掉,然后再将新元素插入进去
(2)
1)resize(n)表示增加n个有效元素。
2)resize(n, data)将vector中元素改变到n个,并且n个元素的值为data。第二个参数可以不用传,默认情况下使用缺省值。
如果增加到某个个数而没有超过vector的实际容量,vector底层的容量不会改变。
3)reserve(n)函数只是将容量增大,不改变元素的个数。