vector的介绍及使用
1.1 vector简介
vector是表示可变大小数组的序列容器。
就像数组一样,vector也采用的连续存储空间来存储元素。也就是意味着可以采用下标对vector的元素进行访问(随机访问),和数组一样高效。但是又不像数组,它的大小是可以动态改变的,而且它的大小会被容器自动处理。
本质讲,vector使用动态分配数组来存储它的元素。当新元素插入时候,这个数组需要被重新分配大小为了增加存储空间。其做法是,分配一个新的数组(直接new一个),然后将全部元素移到这个数组。就时间而言,这是一个相对代价高的任务,因为每当一个新的元素加入到容器的时候,vector并不会每次都重新分配大小。
vector分配空间策略:vector会分配一些额外的空间以适应可能的增长,因为存储空间比实际需要的存储空间更大。不同的库采用不同的策略权衡空间的使用和重新分配。但是无论如何,重新分配都应该是对数增长的间隔大小,以至于在末尾插入一个元素的时候是在常数时间的复杂度完成的。
因此,vector占用了更多的存储空间,为了获得管理存储空间的能力,并且以一种有效的方式动态增长。
与其它动态序列容器相比(deque, list and forward_list), vector在访问元素的时候更加高效,在末
尾添加和删除元素相对高效。对于其它不在末尾的删除和插入操作,效率更低(时间复杂读O(N))。比起list和forward_list
统一的迭代器和引用更好。
1.2 vector的使用
vector的命名空间:
std::vector
vector对应模板
template < class T, class Alloc = allocator<T> > class vector
1.2.1 vector对象定义
vector无参构造函数
vector();
作用:构造一个没有元素的空vector;
形参:无;
返回值:空vector;
vector赋值构造函数
vector (size_type n, const value_type& val = value_type());
作用:构造一个包含n个元素的vector。每个元素都是val。
形参:n是初始化val的个数,value_type就是模板中的T,val是要初始化的值
返回值:vector对象;
exmaple:
#include <iostream>
#include <vector>
int main()
{
std::vector<int> first; // empty vector of ints
std::vector<int> second(4, 100); // four ints with value 100
return 0;
}
result:
![](https://img-blog.csdnimg.cn/img_convert/c216127bb8a8ec4679c1eb38facc51ea.png)
vector迭代器构造函数
vector (InputIterator first, InputIterator last)
作用:构造一个包含与范围[first,last)相同数量元素的vector,其中每个元素都从该范围内对应的元素以相同的顺序构造。
#include <iostream>
#include <vector>
# include<string>
int main()
{
//创建一个字符串
std::string str("whqijyy");
//注意迭代器声明
std::string::iterator begin = str.begin();
//可以使用auto自动匹配
auto end = str.end();
//使用迭代器创建vector
std::vector<char> vector1(begin, end);
//迭代器构造函数也可以用于从数组进行构造:
int array[] = {1,2,3,4,5,6 };
std::vector<int> vector2(array, array + sizeof(array) / sizeof(int));
return 0;
}
reslut:
![](https://img-blog.csdnimg.cn/img_convert/8cc5d9d28b8faef4e5a042c3d05310fd.png)
vector拷贝构造函数
vector (const vector& x);
作用:构造一个vector,其中包含x中每个元素的副本,顺序相同;
形参:vector对象;
输出:拷贝构造后的对象;
example:
#include <iostream>
#include <vector>
int main()
{
//迭代器构造函数也可以用于从数组进行构造:
int array[] = {1,2,3,4,5,6 };
std::vector<int> vector2(array, array + sizeof(array) / sizeof(int));
//拷贝构造
std::vector<int> vector3(vector2);
return 0;
}
result:
![](https://img-blog.csdnimg.cn/img_convert/69471c91d33e24c88d36700f74d8b7a9.png)
1.2.2 vector iterator 的使用
begin() & end()
begin();end();
作用:获取第一个数据位置的iterator/const_iterator, 获取最后一个数据的下一个位置
的iterator/const_iterator
返回值:数据第一个位置;数据最后一个位置的下一个位置;
example:
#include <iostream>
#include <vector>
int main()
{
//迭代器构造函数也可以用于从数组进行构造:
int array[] = {1,2,3,4,5,6 };
std::vector<int> vector2(array, array + sizeof(array) / sizeof(int));
std::vector<int>::iterator begin = vector2.begin();
std::vector<int>::iterator end = vector2.end();
//读取数据
std::cout << "读取数据" << std::endl;
while (begin != end){
std::cout << *begin << ' ';
++begin;
}
std::cout<<std::endl;
//修改数据
std::cout << "修改数据" << std::endl;
begin = vector2.begin();
while (begin != end) {
(*begin)++;
std::cout << *begin << ' ';
++begin;
}
return 0;
}
result:
读取数据
1 2 3 4 5 6
修改数据
2 3 4 5 6 7
rbegin() & rend()
rbegin();rend();
作用:获取最后一个数据位置的reverse_iterator,获取第一个数据前一个位置的reverse_iterator
返回值:数据最后一个位置;数据第一个位置的上一个位置;
example:
#include <iostream>
#include <vector>
int main()
{
//迭代器构造函数也可以用于从数组进行构造:
int array[] = {1,2,3,4,5,6 };
std::vector<int> vector2(array, array + sizeof(array) / sizeof(int));
std::vector<int>::reverse_iterator rbegin = vector2.rbegin();
auto rend = vector2.rend();
//读取数据
std::cout << "读取数据" << std::endl;
while (rbegin != rend){
std::cout << *rbegin << ' ';
++rbegin;
}
std::cout<<std::endl;
//修改数据
std::cout << "修改数据" << std::endl;
rbegin = vector2.rbegin();
while (rbegin != rend) {
(*rbegin)++;
std::cout << *rbegin << ' ';
++rbegin;
}
return 0;
}
result:
读取数据
6 5 4 3 2 1
修改数据
7 6 5 4 3 2
注意:begin和end的声明是std::vector<int>::iterator;rend和rebegin的声明是std::vector<int>::reverse_iterator;当然两者都可以使用auto。
![](https://img-blog.csdnimg.cn/img_convert/ece51a10b8b0a1628228da3775e1b5e3.png)
1.2.3 vector 空间增长问题
size()
size_type size() const;
返回值:返回vector中元素的个数。
example:
#include <iostream>
#include <vector>
int main()
{
//迭代器构造函数也可以用于从数组进行构造:
int array[] = {1,2,3,4,5,6 };
std::vector<int> vector2(array, array + sizeof(array) / sizeof(int));
std::cout << "vector2的size:" << vector2.size() << std::endl;
return 0;
}
relust:
vector2的size:6
capacity()
size_type capacity() const;
返回:当前为vector分配的存储空间大小,以元素表示。
example:
#include <iostream>
#include <vector>
int main()
{
//迭代器构造函数也可以用于从数组进行构造:
int array[] = {1,2,3,4,5,6 };
std::vector<int> vector2(array, array + sizeof(array) / sizeof(int));
std::cout << "vector2的capacity:" << vector2.capacity() << std::endl;
return 0;
}
reslut:
vector2的capacity:6
empty()
bool empty() const;
返回:返回向量是否为空(即它的大小是否为0)。
example:
#include <iostream>
#include <vector>
# include <string>
int main()
{
//迭代器构造函数也可以用于从数组进行构造:
int array[] = {1,2,3,4,5,6 };
std::vector<int> vector2(array, array + sizeof(array) / sizeof(int));
std::cout << "vector2.empty:" << vector2.empty() << std::endl;
return 0;
}
result:
vector2.empty:0
resize()
void resize (size_type n, value_type val = value_type());
作用:调整vector大小,使其包含n个元素。如果n小于当前vector大小,则内容减少到前n个元素,删除超出的元素(并销毁它们)。如果n大于当前容器的大小,内容将通过在末尾插入尽可能多的元素来扩展,以达到n的大小。如果指定了val,则将新元素初始化为val的副本,否则将它们进行值初始化。如果n也大于当前容器容量,则自动重新分配已分配的存储空间。注意size会改变。
example:
#include <iostream>
#include <vector>
# include <string>
int main()
{
//迭代器构造函数也可以用于从数组进行构造:
int array[] = {1,2,3,4,5,6 };
std::vector<int> vector2(array, array + sizeof(array) / sizeof(int));
std::cout << "vector2.size():" <<vector2.size()<< std::endl;
std::cout << "n < vector2.size():" <<std::endl;
vector2.resize(5, 2);
for (auto e : vector2) {
std::cout << e;
}
std::cout << std::endl;
std::cout << "n > vector2.size():" << std::endl;
vector2.resize(10, 2);
for (auto e : vector2) {
std::cout << e;
}
std::cout << std::endl;
return 0;
}
result:
vector2.size():6
n < vector2.size():
12345
n > vector2.size():
1234522222
reserve()
void reserve (size_type n);
作用:改变vector的容量;
注意:如果n大于当前vector容量,该函数将导致容器重新分配其存储空间,将其容量增加到n(或更大)。在所有其他情况下,函数调用不会导致重新分配,vector容量也不会受到影响。
example:
#include <iostream>
#include <vector>
# include <string>
int main()
{
//迭代器构造函数也可以用于从数组进行构造:
int array[] = {1,2,3,4,5,6 };
std::vector<int> vector2(array, array + sizeof(array) / sizeof(int));
std::cout << "vector2.capacity():" <<vector2.capacity()<< std::endl;
std::cout << "n < vector2.capacity():" <<std::endl;
vector2.reserve(4);
std::cout << vector2.capacity() << std::endl;
//创建一个与vector2相同的vector
std::vector<int> tmp(array, array + sizeof(array) / sizeof(int));
std::cout << "n > vector2.capacity():" << std::endl;
vector2.reserve(10);
std::cout << vector2.capacity() << std::endl;
return 0;
}
result:
vector2.capacity():6
n < vector2.capacity():
6
n > vector2.capacity():
10
vector扩容机制
vector的capacity扩容在vs和g++下分别运行会发现,vs下capacity是按1.5倍增长的,g++是按2倍增长的。这个问题经常会考察,不要固化的认为,vector增容都是2倍,具体增长多少是根据具体的需求定义的。vs是PJ版本STL,g++是SGI版本STL。
reserve只负责开辟空间,如果确定知道需要用多少空间,reserve可以缓解vector增容的代价缺陷问
题。
resize在开空间的同时还会进行初始化,影响size。
1.2.4 vector 增删查改
push_back()
void push_back (const value_type& val);
在vector的最后一个元素之后添加一个新元素。val的内容被复制(或移动)到新元素中;
example:
// vector::push_back
#include <iostream>
#include <vector>
int main()
{
std::vector<int> myvector;
int myint;
std::cout << "Please enter some integers (enter 0 to end):\n";
do {
std::cin >> myint;
myvector.push_back(myint);
} while (myint);
std::cout << "myvector stores " << int(myvector.size()) << " numbers.\n";
return 0;
}
input & reslut:
Please enter some integers (enter 0 to end):
1
2
3
4
5
6
0
myvector stores 7 numbers.
pop_back()
void pop_back();
作用:删除vector中的最后一个元素,有效地将容器大小减少1。这将破坏被删除的元素。
example:
// vector::pop_back
#include <iostream>
#include <vector>
int main()
{
std::vector<int> myvector;
//创建数据
myvector.push_back(100);
myvector.push_back(200);
myvector.push_back(300);
std::cout << "原始数据" << std::endl;
for (auto e : myvector) {
std::cout << e << " ";
}
std::cout << std::endl;
while (!myvector.empty())
{
myvector.pop_back();
for (auto e : myvector) {
std::cout << e << " ";
}
std::cout << std::endl;
}
return 0;
}
result:
原始数据
100 200 300
100 200
100
insert()
iterator insert (iterator position, const value_type& val);
作用:在position位置插入val;其他元素向后挪动;注意所有的位置都是用迭代器表示的。
example:
// inserting into a vector
#include <iostream>
#include <vector>
int main()
{
std::vector<int> myvector(3, 100);
std::cout << "原始vector:" << std::endl;
for (auto e : myvector) {
std::cout << e << " ";
}
std::cout << std::endl;
std::vector<int>::iterator it;
std::cout << "原始iterator指向的元素:" << std::endl;
it = myvector.begin();
std::cout << *it << std::endl;
it = myvector.insert(it, 200);
std::cout << "插入后的vector:" << std::endl;
for (auto e : myvector) {
std::cout << e << " ";
}
std::cout << std::endl;
std::cout << "插入后iterator指向的元素:" << std::endl;
std::cout << *it << std::endl;
return 0;
}
result:
原始vector:
100 100 100
原始iterator指向的元素:
100
插入后的vector:
200 100 100 100
插入后iterator指向的元素:
200
void insert (iterator position, size_type n, const value_type& val);
作用:在position位置插入n个元素;元素为val;
example:
// inserting into a vector
#include <iostream>
#include <vector>
int main()
{
std::vector<int> myvector(3, 100);
std::cout << "原始vector:" << std::endl;
for (auto e : myvector) {
std::cout << e << " ";
}
std::cout << std::endl;
std::vector<int>::iterator it;
it = myvector.begin();
myvector.insert(it, 2, 20);
std::cout << "插入后的vector:" << std::endl;
for (auto e : myvector) {
std::cout << e << " ";
}
return 0;
}
result:
原始vector:
100 100 100
插入后的vector:
20 20 100 100 100
void insert (iterator position, InputIterator first, InputIterator last);
作用:在位置position插入区间[first,last)的元素;
example:
// inserting into a vector
#include <iostream>
#include <vector>
int main()
{
std::vector<int> myvector;
myvector.push_back(1);
myvector.push_back(2);
myvector.push_back(3);
std::cout << "原始vector:" << std::endl;
for (auto e : myvector) {
std::cout << e << " ";
}
std::cout << std::endl;
std::vector<int>::iterator begin = myvector.begin();
std::vector<int>::iterator end = myvector.end();
myvector.insert(begin, begin, end);
std::cout << "插入后的vector:" << std::endl;
for (auto e : myvector) {
std::cout << e << " ";
}
return 0;
}
result:
原始vector:
1 2 3
插入后的vector:
1 2 3 1 2 3
operator[]
reference operator[] (size_type n);const_reference operator[] (size_type n) const;
作用:重载[]运算符,可以让vector支持随机访问;
example:
// inserting into a vector
#include <iostream>
#include <vector>
int main()
{
//使用数组创建vector:
int arr[] = {1,2,3,4,5,6};
//迭代器创建vector
std::vector<int> myvector(arr, arr + sizeof(arr) / sizeof(int));
//遍历vector
for (size_t i = 0; i < myvector.size(); ++i) {
std::cout << myvector[i] << " ";
}
std::cout << std::endl;
return 0;
}
result:
1 2 3 4 5 6
erase()
iterator erase (iterator position);
iterator erase (iterator first, iterator last);
作用:删除position位置的元素;删除区间[first,last)之间的元素。
example:
// inserting into a vector
#include <iostream>
#include <vector>
int main()
{
//使用数组创建vector:
int arr[] = {1,2,3,4,5,6};
//迭代器创建vector
std::vector<int> myvector(arr, arr + sizeof(arr) / sizeof(int));
std::cout << "原始vector:" << std::endl;
for (auto e : myvector) {
std::cout << e << " ";
}
std::cout << std::endl;
//获取迭代器:
std::vector<int>::iterator begin = myvector.begin();
//删除一个元素
myvector.erase(begin);
std::cout << "删除第一个元素后的vector:" << std::endl;
for (auto e : myvector) {
std::cout << e << " ";
}
std::cout << std::endl;
//获取迭代器:
std::vector<int>::iterator begin1 = myvector.begin();
//删除一个元素
myvector.erase(begin1,begin1+2);
std::cout << "再删除两个后的vector:" << std::endl;
for (auto e : myvector) {
std::cout << e << " ";
}
std::cout << std::endl;
return 0;
}
result:
原始vector:
1 2 3 4 5 6
删除第一个元素后的vector:
2 3 4 5 6
再删除两个后的vector:
4 5 6