vector是一个封装了动态数组的顺序容器,vector可以存储各种类型的数据。
vector的特性
(1)顺序容器
在内存中的存储是连续的,可以通过元素在序列中的位置访问对应的元素。
(2)动态数组
支持对序列中的任意元素进行快速直接访问,甚至可以通过指针算述进行该操作。提供了在序列末尾相对快速地添加/删除元素的操作。
基本函数
构造函数
vector() | 创建一个空vector |
vector(int n) | 创建一个vector,元素个数为n |
vector(int n,const t& x) | 创建一个vector,元素个数为n,且值均为x |
vector(const vector&) | 拷贝构造,复制一个一样的vector容器 |
vector(begin,end) | 复制[begin,end)区间内另一个数组的元素到vector中 |
迭代器iterator用于访问容器中的元素,iterator begin()函数可以理解为返回这个容器的第一个元素的位置,类似指针,将其称作迭代器。在不同的容器中迭代器实现方法不同,但使用方法一致。begin()返回值皆是第一个元素的位置,end()返回最后一个元素下一个的位置。
int main()
{
vector<int>s1;
vector<int>s2(5);
vector<int>s3(5,1);
vector<int>s4(s3);
//从s3的初始位置+2开始到结束这段数据作为参数初始化
vector<int>s5(s3.begin()+2, s3.end());
cout << "vector(): ";
for (auto a : s1)
{
cout << a << " ";
}
cout << endl;
cout << "vector(int n): ";
for (auto a : s2)
{
cout << a << " ";
}
cout << endl;
cout << "vector(int n,const t& x): ";
for (auto a : s3)
{
cout << a << " ";
}
cout << endl;
cout << "vector(const vector&): ";
for (auto a : s4)
{
cout << a << " ";
}
cout << endl;
cout << "vector(begin,end): ";
for (auto a : s5)
{
cout << a << " ";
}
cout << endl;
return 0;
}
注:s1创建的是一个空vector,没有内容可以打印。
插入函数
void push_back(const T& x) | 尾部插入一个元素x |
iterator insert(iterator it,const T& x) | 向迭代器指向元素前增加一个元素x |
iterator insert(iterator it,int n,const T& x) | 向迭代器指向元素前增加n个相同的元素x |
iterator insert(iterator it,const_iterator first,const_iterator last) | 向迭代器指向元素前,插入一个区间(区间为[first,last))的元素 |
int main()
{
vector<int>arr;
arr.push_back(1);
arr.push_back(2);
arr.push_back(3);
for (auto a : arr)
{
cout << a << " ";
}
cout << endl;
arr.insert(arr.begin() + 1, 0);
for (auto a : arr)
{
cout << a << " ";
}
cout << endl;
arr.insert(arr.begin() + 3, 3, 0);
for (auto a : arr)
{
cout << a << " ";
}
cout << endl;
vector<int>arr2({7,8,9});
arr.insert(arr.begin(), arr2.begin(), arr2.end());
for (auto a : arr)
{
cout << a << " ";
}
cout << endl;
return 0;
}
插入时的迭代器失效问题
在上面也说过,迭代器用于访问存储的元素,但是更确切地说,它是指向要访问元素的位置。所以会有以下问题。
开始时,迭代器指向3,按照我们所希望的它应该一直指向3。但在迭代器指向位置前插入一个数据,此时迭代器指向了2。像这样的情况我们称作迭代器失效。(插入位置以及其之后的迭代器都会失效)
对于迭代器会失效的问题,最好的方法是及时更新迭代器。
删除函数
iterator erase(iterator it) | 删除vector中迭代器指向元素 |
iterator erase(iterator first,iterator last) | 删除vector中[first,last)中元素 |
void pop_back() | 删除vector中最后一个元素 |
void clear() | 清空vector中所有元素 |
int main()
{
vector<int>arr({ 1, 2, 3, 4, 5, 6, 7, 8, 9 });
arr.pop_back();
cout << "pop_back():";
for (auto a : arr)
{
cout << a << " ";
}
cout << endl;
cout << "erase(iterator first, iterator last):";
arr.erase(arr.begin(), arr.begin() + 3);
for (auto a : arr)
{
cout << a << " ";
}
cout << endl;
cout << "erase(iterator it):";
arr.erase(arr.begin() + 3);
for (auto a : arr)
{
cout << a << " ";
}
cout << endl;
cout << "clear():";
arr.clear();
for (auto a : arr)
{
cout << a << " ";
}
cout << endl;
return 0;
}
删除时的迭代器失效问题
删除时也是同样的,指向的位置没有变,但数据被挪动了(删除的位置以及之后的迭代器失效)。还是那句话,及时更新迭代器能避免失效的问题。
常用函数
reference at(int pos) | 返回pos位置元素的引用 |
reference front() | 返回首元素的引用 |
reference back() | 返回尾元素的引用 |
iterator begin() | 返回vector头指针,指向第一个元素 |
iterator end() | 返回vector尾指针,指向向量最后一个元素的下一个位置 |
reverse_iterator rbegin() | 反向迭代器,指向最后一个元素 |
reverse_iterator rend() | 反向迭代器,指向第一个元素之前的位置 |
int size() const | 返回vector中元素的个数 |
int capacity() const | 返回当前vector所能容纳的最大元素值 |
int max_size() const | 返回最大可允许的vector元素数量值 |
bool empty() const | 判断vector是否为空,若为空,则向量中无元素 |
void swap(vector&) | 交换两个存储同类型vector的数据 |
at函数和重载[]的区别:at函数会做边界检查,而[]不会。
范围for
auto这个类型会自动推到接收的类型,而范围for的写法如下:
a会从头到尾依次接收arr中存储的数据。而凡是有迭代器的容器都可以使用范围for
for (auto a : arr)
{
//函数体
}
为什么有迭代器就可以使用范围for:
编译器眼中的范围for其实就是迭代器遍历,类似下面的这个代码。
vector<int>::iterator it = arr.begin();
while (it != arr.end()){
//函数体
it++;
}
int main()
{
vector<int>arr({ 1, 2, 3, 4, 5, 6, 7, 8, 9 });
//范围for的本质:
vector<int>::iterator it = arr.begin();
while (it != arr.end())
{
cout << *it << " ";
it++;
}
cout << endl;
//在编译器的眼中,范围for实际上就是上面的while循环
for (auto a : arr)
{
cout << a << " ";
}
cout << endl;
return 0;
}