定义:
1、vector是表示可变大小数组的序列容器。
2、就像数组一样,vector也采用的连续存储空间来存储元素。也就是意味着可以采用下标对vector的元素进行访问,和数组一样高效。但是又不像数组,它的大小是可以动态改变的,而且它的大小会被容器自动处理。
3、本质讲,vector使用动态分配数组来存储它的元素。当新元素插入时候,这个数组需要被重新分配大小为了增加存储空间。其做法是,分配一个新的数组,然后将全部元素移到这个数组。就时间而言,这是一个相对代价高的任务,因为每当一个新的元素加入到容器的时候,vector并不会每次都重新分配大小。
4、vector分配空间策略:vector会分配一些额外的空间以适应可能的增长,因为存储空间比实际需要的存储空间更大。不同的库采用不同的策略权衡空间的使用和重新分配。但是无论如何,重新分配都应该是对数增长的间隔大小,以至于在末尾插入一个元素的时候是在常数时间的复杂度完成的。
因此,vector占用了更多的存储空间,为了获得管理存储空间的能力,并且以一种有效的方式动态增长。
5、与其它动态序列容器相比(deques, lists and forward_lists), vector在访问元素的时候更加高效,在末尾添加和删除元素相对高效。对于其它不在末尾的删除和插入操作,效率更低。比起lists和forward_lists统一的迭代器和引用更好。
使用:
1、引用头文件
#include<vector>
2、定义vector
vector<int> A; //声明一个int型向量
vector<int> A(5); //声明一个初始大小为5的int向量
vector<int> A(10, 1); //声明一个初始大小为10且值都是1的向量
vector<int> A(tmp); //声明并用tmp向量初始化vec向量
vector<int> tmp(A.begin(), A.begin() + 3); //用向量vec的第0个到第2个值初始化tmp
int arr[5] = {1, 2, 3, 4, 5};
vector<int> A(arr, arr + 5); //将arr数组的元素用于初始化A向量
//说明:当然不包括arr[4]元素,末尾指针都是指结束元素的下一个元素,
//这个主要是为了和vec.end()指针统一。
vector<int> A(&arr[1], &arr[4]); //将arr[1]~arr[4]范围内的元素作为A的初始值
3、vector操作
(1)属性
向量大小: A.size();
向量最大容量: A.max_size();
更改向量大小: A.resize();
std::vector<int> myvector;
for (int i=1;i<10;i++) myvector.push_back(i);
此时 向量实际内容:1.2.3.4.5.6.7.8.9
myvector.resize(5);
此时 向量实际内容:1.2.3.4.5.
myvector.resize(8,100);
此时 向量实际内容:1.2.3.4.5.100.100.100
myvector.resize(12);
此时 向量实际内容:1.2.3.4.5.100.100.100.0.0.0.0
向量真实大小: A.capacity();返回int类型
向量判空: A.empty(); 返回bool类型是否为空
减少向量大小到满足元素所占存储空间的大小: A.shrink_to_fit();
std::vector<int> myvector(100);
myvector.capacity() =100
//建立的是一个100单位的向量
myvector.resize(10);
myvector.capacity() =100
//缩放到10单位向量但是整体没有改变
myvector.shrink_to_fit();
myvector.capacity() =10
//缩小到真实单位
调用shrink_to_fit是向实现明确不需要多余的存储以便按需优化(有时候实现比你更清楚什么时候更方便释放),
而非对容器占用存储的操作(事实上容器的存储怎么分配怎么使用就不是容器直接提供的接口管得到的),
用在你不在乎一定需要释放但希望实现有机会利用你用不到的资源的时候。
(2)操作
多个元素赋值: vec.assign(); //类似于初始化时用数组进行赋值
末尾添加元素: vec.push_back();
末尾删除元素: vec.pop_back();
任意位置插入元素: vec.insert();
任意位置删除元素: vec.erase();
交换两个向量的元素: vec.swap();
清空向量元素: vec.clear();
```
{
std::vector<int> myvector;
std::vector<int> myvector1(1,1);
myvector.push_back(10);
myvector.push_back(10);
myvector.push_back(10);
myvector.push_back(10);
//向量内容:10.10.10.10
myvector.pop_back();
//向量内容:10.10.10
myvector.insert(myvector.begin(), 8);//在最前面插入新元素。
//向量内容:8.10.10.10
myvector.insert(myvector.begin() + 2, 1);//在迭代器中第二个元素前插入新元素
//向量内容:8.10.1.10.10
myvector.insert(myvector.end(), 3);//在向量末尾追加新元素。
//向量内容:8.10.1.10.10.3
myvector.insert(myvector.end(),5,3); //从myvector.back位置插入5个值为3的元素
//向量内容:8.10.1.10.10.3.5.5.5.5.5
myvector.erase(myvector.begin());//删除头一个元素
//向量内容:10.1.10.10.3.5.5.5.5.5
myvector.erase(myvector.end()-5,myvector.end());//删除后5个元素
//向量内容:10.1.10.10.3
myvector.swap(myvector1);
//交换之后
//myvector向量内容:10.1.10.10.3
//myvector1向量内容:1
//myvector向量内容:1
//myvector1向量内容:10.1.10.10.3
//一般用于当我们插入数据完成之后,想要释放多余的空间如果案例如下
//我们想强行释放vector所占的内存,那么可以:
std::vector<int>().swap(myvector);
getchar();
return 0;
}
std::vector<int> myvector();
myvector.reserve(100);//给了100单位的空间
myvector.push_back(1);
myvector.push_back(1);
myvector.push_back(1);
myvector.push_back(1);//只给了四个元素
cout<<myvector.size()<<endl; //4
cout<<myvector.capacity()<<endl;//读取的实际100
vector<int>(myvector).swap(myvector);通过交换将多余的释放
cout<<myvector.size()<<endl;//4
cout<<myvector.capacity()<<endl;//4
vector<int>().swap(myvector);//完全释放
cout<<myvector.size()<<endl;//0
cout<<myvector.capacity()<<endl;//0 释放了
(3)迭代器
开始指针:vec.begin();
末尾指针:vec.end(); //指向最后一个元素的下一个位置
指向常量的开始指针: vec.cbegin(); //意思就是不能通过这个指针来修改所指的内容,但还是可以通过其他方式修改的,而且指针也是可以移动的。
指向常量的末尾指针: vec.cend();
auto i1 = Container.begin(); // i1 is Container<T>::iterator
auto i2 = Container.cbegin(); // i2 is Container<T>::const_iterator
1.iterator,const_iterator作用:遍历容器内的元素,并访问这些元素的值。iterator可以改元素值,但const_iterator不可改。跟C的指针有点像。
2.const_iterator 对象可以用于const vector 或非 const vector,它自身的值可以改(可以指向其他元素),但不能改写其指向的元素值。
3.cbegin()和cend()是C++11新增的,它们返回一个const的迭代器,不能用于修改元素。
(4)数据的访问
下标访问: vec[1]; //并不会检查是否越界
at方法访问: vec.at(1); //以上两者的区别就是at会检查是否越界,是则抛出out of range异常
访问第一个元素: vec.front();
访问最后一个元素: vec.back();
返回一个指针: int* p = vec.data(); //可行的原因在于vector在内存中就是一个连续存储的数组,所以可以返回一个指针指向这个数组。这是是C++11的特性。
遍历元素
vector<int>::iterator it;
for (it = vec.begin(); it != vec.end(); it++)
cout << *it << endl;
//或者
for (size_t i = 0; i < vec.size(); i++) {
cout << vec.at(i) << endl;
}
元素翻转
#include <algorithm>
reverse(vec.begin(), vec.end());
#include <algorithm>
sort(vec.begin(), vec.end()); //采用的是从小到大的排序
//如果想从大到小排序,可以采用上面反转函数,也可以采用下面方法:
bool Comp(const int& a, const int& b) {
return a > b;
}
sort(vec.begin(), vec.end(), Comp);