Vector 容器类
一、Vector简介
Vector(向量)是一个能够存放任意类型的动态数组,能够增加和压缩数据。
二、Vector容器特性
1、顺序序列
顺序容器中的元素按照严格的线性顺序排列。可以通过元素在序列中的位置访问对应的元素,即通过下标访问。
2、动态数组
支持对序列中的任意元素进行快速直接查询,甚至可以通过指针算数进行该操作,提供了在序列末尾相对快速地添加/删除元素的操作。类似于栈一样,只能在最后进行添加删除操作,当我们不知道自己所需的数组大小时,可以用Vector以节约空间。vector容器的大小可以自动增长,需要在代码中包含头文件**#include <vector>**
三、基本函数及用法
vector<int> v; //不指定长度
vector<int> v(n); // 指定长度为n
vector<int> v{1,2,3}; //一维vector直接赋值
vector<vector<int> > v2{{1,2,3},{4,5,6}}; //二维vector直接赋值
v.pop_back(); //删除最后一个元素
v.push_back(elem); //在尾部加入一个元素
v.size(); //返回容器的大小,即当前使用数据的大小
v.capacity; //返回容器当前能够容纳的元素数量,即当前vector分配的大小
v.max_size(); // 得到vector最大可以是多大
v.resize(); // 改变当前使用数据的大小,如果它比当前使用的大,者填充默认值
v.reserve(); // 改变当前vecotr所分配空间的大小
v.at(); //得到编号位置的数据
v.begin(); // 得到数组头的指针
v.end(); // 得到数组的最后一个元素+1的指针
v.front(); // 得到数组头的引用
v.back(); // 得到数组的最后一个单元的引用
v.erase(); // 删除指针指向的数据项
v.clear(); // 清空当前的vector
v.rbegin(); // 将vector反转后的开始指针返回(其实就是原来的end-1)
v.rend(); // 将vector反转构的结束指针返回(其实就是原来的begin-1)
v.empty(); // 判断vector是否为空
v.swap(); // 与另一个vector交换数据
sort(a.begin(),a.end());
//对a中的从a.begin()(包括它)到a.end()(不包括它)的元素进行从小到大排列
reverse(a.begin(),a.end());
//对a中的从a.begin()(包括它)到a.end()(不包括它)的元素倒置,但不排列,如a中元素为1,3,2,4,倒置后为4,2,3,1
copy(a.begin(),a.end(),b.begin()+1);
//把a中的从a.begin()(包括它)到a.end()(不包括它)的元素复制到b中,从b.begin()+1的位置(包括它)开始复制,覆盖掉原有元素
find(a.begin(),a.end(),10);
//在a中的从a.begin()(包括它)到a.end()(不包括它)的元素中查找10,若存在返回其在向量中的位置
四、应用举例
**对 v.size()和 v.capacity()的补充:*,例如以下程序,可以看出程序自动的进行了扩容。即如果添加了一个元素,导致超过当前容器的容景,容量会自动增加。
#include <vector>
#include <iostream>
#include <iterator>
#include <string>
using namespace std;
int main()
{
vector<string> array;
array.reserve(5);
//append some elements
array.push_back("one");
array.push_back("two");
array.push_back("three");
array.push_back("four");
array.push_back("!");
copy(array.begin(), array.end(), ostream_iterator<string>(cout, " "));
//用于获取一个元素,同时保存在缓冲器中,可以供Cout输出, 关联cout,设置分隔符
cout << endl;
cout << "max_size():" << array.max_size() << endl;
cout << "size():" << array.size() << endl;
cout << "capacity():" << array.capacity() << endl;
cout << "----------------------------" << endl;
//swap second and fourth element
swap(array[1], array[3]);
//insert element "always" before element "?"
array.insert(find(array.begin(), array.end(), "!"), "five");
//assign "!" to the last element
array.back() = "six";
copy(array.begin(), array.end(), ostream_iterator<string>(cout, " "));
cout << endl;
// return maximum possible length of sequence
//回容器的最大可以存储的元素个数,这是个极限,当容器扩展到这个最大值时就不能再自动增大
cout << "max_size():" << array.max_size() << endl;
// return length of sequence
cout << "size():" << array.size() << endl;
// return current length of allocated storage
cout << "capacity():" << array.capacity() << endl;
return 0;
}
输出结果如下:
one two three four !
max_size():461168601842738790
size():5
capacity():5
----------------------------
one four three two five six
max_size():461168601842738790
size():6
capacity():7
当vector容器大小超过capacity时,vector会重新配置内部的存储器,这样就会导致和vector元素相关的所有reference、pointers、iterator都会失效,另外内存的重新配置会很消耗时间。
例如对以下程序:
#include <vector>
#include <iostream>
#include <iterator>
#include <string>
using namespace std;
int main( )
{
vector<string> m_vector;
m_vector.reserve(5);//当前空间够大,不会发生重新配置,插入新元素后有可能会重新分配
m_vector.push_back("hello");
m_vector.push_back("C++");
m_vector.push_back("world");
vector<string>::iterator it = m_vector.begin();
cout << "change size before, the first elemt is :" << *it << endl;
cout << "push_back one elems......" << endl;
m_vector.push_back("one");
cout << "push_back one elemt after, the first elemt is :" << *it << endl;
cout << "push_back two elems......" << endl;
m_vector.push_back("two");
m_vector.push_back("Censh");//当前大小超过当前的容量,导致重新分配内存
//it = m_vector.begin(); //内存重新分配后,重新获取指针可以避免指针失效
cout << "push_back two elemts after, the first elemt:" << *it << endl;//指针失效导致程序奔溃,
return 0;
}
输出结果:
change size before, the first elemt is :hello
push_back one elems…
push_back one elemt after, the first elemt is :hello
push_back two elems…
push_back two elemts after, the first elemt:hello
而当屏蔽掉以上程序倒数第四行的 it = m_vector.begin(); 之后,程序会崩溃,这是因为在最后push_back的时候容器当前大小超过当前的容量,导致了重新分配内存,这样就会导致和vector元素相关的所有reference、pointers、iterator都会失效,而内存重新分配后,重新获取指针可以避免指针失效 ,所以应尽量避免内存重新配置,常有的方法有:
1、reverse()时保留适当空间 2、利用构造函数创建出足够的空间 ,如:vector<int> v(80);
以上的补充:迭代器,要访问顺序容器和关联容器中的元素,需要通过“迭代器(iterator)”进行。迭代器是一个变量,相当于容器和操纵容器的算法之间的中介。迭代器可以指向容器中的某个元素,通过迭代器就可以读写它指向的元素。从这一点上看,迭代器和指针类似。
常用的正向迭代器:容器类名:: iterator 迭代器名; 例如:
vector<int>::iterator my_iter;
使用举例:
vector<int>::iterator it;
for(it=vec.begin();it!=vec.end();it++)
cout<<*it<<endl;
下面看看使用vector创建二维数组:
例如:vector <vector <int> > array(3); (需要注意> >之间的空格,据说有的编译器里面(即使c++11)会出错),但是在这里试验时没加空格并没有出错,
#include <string.h>
#include <vector>
#include <iostream>
#include <algorithm>
using namespace std;
constexpr auto N = 5;
constexpr auto M = 7;
int main()
{
vector<vector<int>> m_vector(N); //定义二维动态数组大小为5行 ,在这里试验了一下> >之间没有空格,正常编译的
for (int i = 0; i < m_vector.size(); i++)//动态二维数组为5行7列,值全为0
{
m_vector[i].resize(M);
}
for (int i = 0; i < m_vector.size(); i++)//输出二维动态数组
{
for (int j = 0; j < m_vector[i].size(); j++)
{
cout << m_vector[i][j] << " ";
}
cout << endl;
}
return 0;
}
另外一种方法创建二维数组:
#include <string.h>
#include <vector>
#include <iostream>
#include <algorithm>
using namespace std;
constexpr auto M = 5;
constexpr auto N = 7;
int main()
{
vector<vector<int> > m_vector(M, vector<int>(N)); //定义二维动态数组5行7列
for (int i = 0; i < m_vector.size(); i++)//输出二维动态数组
{
for (int j = 0; j < m_vector[i].size(); j++)
{
cout << m_vector[i][j] << " ";
}
cout << endl;
}
return 0;
}
以上两种方法输出结果一样
注意:下标的方式只能读取已经存在的元素而不能写入,写入一般用push_back,例如以下是错误的:
vector<int> a;
for(int i=0;i<10;i++)
a[i]=i; //错误,
另外vector的内存释放可以参考:https://blog.youkuaiyun.com/msdnwolaile/article/details/52708144
本文参考:
https://www.cnblogs.com/jinxiang1224/p/8468420.html
https://www.runoob.com/w3cnote/cpp-vector-container-analysis.html