vector容器(动态数组,可变数组)
单口容器
vector动态增长的基本原理
当插入新元素时,如果空间不足,那么vector会重新申请更大的一块内存空间,将原来空间拷贝到新空间上,释放旧空间的数据,再把新元素插入新申请的空间。
默认会申请两倍的新空间,但当空间达到一定大小时,会动态调整其增长策略
#include<iostream>
#include<vector>
using namespace std;
void PrintVector(vector<int>& v) {
for (vector<int>::iterator it = v.begin(); it != v.end(); it++) {
cout << "the val is " << *it << endl;
}
}
//初始化方法
void VectorTest1() {
vector<int> v1; //默认构造
int arr[] = { 10,20,30 };
vector<int> v2(arr, arr + sizeof(arr) / sizeof(int)); //含参构造,第一个参数是容器开始位置,第二个参数是容器结束位置
vector<int> v3(v2.begin(),v2.end());
vector<int> v4(v3); //拷贝构造
PrintVector(v4);
}
//常用赋值操作
void VectorTest2() {
int arr[] = { 10,20,30 };
vector<int> v1(arr, arr + sizeof(arr) / sizeof(int));
vector<int> v2;
//成员方法
v2.assign(v1.begin(), v1.end());
//重载
vector<int> v3;
v3 = v2;
int arr1[] = { 100,200,300 };
vector<int> v4(arr1, arr1 + sizeof(arr) / sizeof(int));
//交换函数的本质是指针的交换
v4.swap(v1);
cout << "v1" << endl;
PrintVector(v1);
cout << "v2" << endl;
PrintVector(v2);
cout << "v3" << endl;
PrintVector(v3);
cout << "v4" << endl;
PrintVector(v4);
//可以看到,只是赋值,并没有跟随原数据交换而改变
}
int main() {
VectorTest2();
return 0;
}
vector大小操作
#include<iostream>
#include<vector>
using namespace std;
void PrintVector1(vector<int>& v) {
for (vector<int>::iterator it = v.begin(); it != v.end(); it++) {
cout << "the val is " << *it << endl;
}
}
void vector1() {
int arr[] = { 10,20,30 };
vector<int> v1(arr, arr + sizeof(arr) / sizeof(int));
int num = v1.size(); //返回容器中元素的个数
cout << "v1的大小为:" << num << endl;
if (v1.empty()) { //判断容器是否为空
cout << "v1容器是空的" << endl;
}
else {
cout << "v1容器不是空的" << endl;
}
v1.resize(5, 66); //重新指定容器大小,变短则删除多余数据
//只写一个参数时,变长以默认值填充,两个参数时,以第二个参数填充
PrintVector1(v1);
v1.resize(7);
int num2 = v1.size(); //返回容器中元素的个数
cout << "v1的新大小为:" << num2 << endl;
PrintVector1(v1);
cout << "v1的容量是:"<<v1.capacity() << endl; //capacity函数获取数组容量
//size表示元素个数,capacity表示能容纳最多的元素,容量一定大于等于size
}
int main() {
vector1();
return 0;
}
vector存取数据操作
#include<iostream>
#include<vector>
using namespace std;
void PrintVector2(vector<int>& v) {
for (vector<int>::iterator it = v.begin(); it != v.end(); it++) {
cout << "the val is " << *it << endl;
}
}
//vector数据存取
void vectorTest4(){
int arr[] = { 10,20,30 };
vector<int> v1(arr, arr + sizeof(arr) / sizeof(int));
for (int i = 0; i < v1.size(); i++) {
cout << v1[i] << endl;
}
for (int i = 0; i < v1.size(); i++) {
cout << v1.at(i) << endl;
}
//两种区别,at在越界时会抛出异常,[]越界时不会抛出异常,直接报错
cout << "第一个元素是:"<<v1.front() << endl; //获取容器第一个数据元素
cout <<"最后一个元素是:"<< v1.back() << endl; //获取容器最后一个数据元素
}
//vector插入和删除
void vectorTest5() {
vector<int> v;
v.push_back(56); //像容器末尾加入一个元素
v.push_back(6);
v.push_back(12);
v.pop_back(); //从元素末尾删除一个元素
//头插法,把数据插入到容器头部
v.insert(v.begin(), 199); //insert函数用来插入数据到指定位置,第一个传入的数据格式是迭代器
v.insert(v.end(), 250);
v.insert(v.begin() + 2, 50); //vector容器支持随机访问,所以可以通过+2访问容器内部元素
//一般支持[]数组下标访问的,都支持随机访问
//不支持随机访问的,只能通过++,或+1,不断遍历得到目标元素
PrintVector2(v);
cout << "----------------------------" << endl;
v.erase(v.begin()); //删除指定元素,参数格式是迭代器
v.erase(v.begin() + 1, v.begin() + 3); //删除指定区间元素,取左留右
PrintVector2(v);
cout << "----------------------------" << endl;
v.clear(); //清空容器内元素
cout << "the size of v is " << v.size() << endl;
}
int main() {
vectorTest5();
return 0;
}
巧用swap缩减空间
//巧用swap缩减空间
//vector 在空间不足时会自动增加,但是在删除元素时,并不会自动减少
void vectorTest6() {
vector<int> v;
for (int i = 0; i < 10000; i++) {
v.push_back(i);
}
cout << "当前v内元素有" << v.size() << "个,容量为 " <<v.capacity() << endl;
v.resize(10);
cout << "删除后v内元素有" << v.size() << "个,容量为 " << v.capacity() << endl;
//可以看到虽然调整了大小,可是容量没有变,浪费空间
//所以利用swap巧妙缩减空间,前一个v可以按照后一个v的size初始化大小,而后一个v在交换后名存实亡
vector<int>(v).swap(v);
cout << "调整大小后v内元素有" << v.size() << "个,容量为 " << v.capacity() << endl;
}
reserve预留空间提高程序效率
reserve和resize区别:
reserve是容器预留空间,但在空间内不真正创建元素对象,所以在没有添加新的对象之前,不能引用容器内的元素。
resize是改变容器的大小,且在创建对象,因此,调用这个函数之后,就可以引用容器内的对象了
void ReverseTest() {
//reserve预留空间
int num = 0; //用来记录申请与释放次数
int* address = NULL; //用来记录容器内元素首地址
vector<int> v;
v.reserve(10000); //预留空间
for (int i = 0; i < 10000; i++) {
//判断在增加一万个元素过程中,进行了多少次元素的申请与释放
v.push_back(i);
if (address != &(v[0])) {
/*
&(v[0])表示容器内首个元素的地址
元素在申请释放过程中,首地址会发生变化
所以以此地址为标准判断
不可以取容器首地址 &v ,因为申请释放过程中容器地址不变
*/
address = &(v[0]);
num++;
}
}
cout << num << endl;
/*
经过对比,用reserve预留空间前需要申请24次内存,
但是预留后,只需要一次
所以如果提前知道大致要存储的元素数量,可以用reserve预留空间,优化程序
*/
}