STL中容器vector -- 讲解超详细
序言
在上一节已经学习了string的接口和模拟实现,vector的接口和string大差不差,重点是vector的模拟实现和迭代器失效的问题!!!

这是vector的一些常用的接口,下面分别来讲解:
1. vector常见的构造函数
| 无参构造 | vector() |
| 传值构造 | vector(size_t n, const value_type& val = value_type()) |
| 拷贝构造 | vector(const vector& x) |
| 迭代器构造 | vector(iterator first,iterator last) |
| 初始化列表构造 | vector(initializer_list()<value_type> it) |
void test01()
{// 无参构造vector<int> v1;// 传值构造vector<int> v2(10, 1); // 初始化为10个1vector<int> v3(10); // 初始化为10个0(初始化的值由编译器决定)// 初始化列表构造vector<int> v4({ 1,2,3,4,5,6,7,8,9,10 });// 迭代器构造vector<int> v5(v4.begin() + 5, v4.end());vector<int>::iterator it = v5.begin();while (it != v5.end()){cout << (*it) << " ";it++;}cout << endl;
}2. vector的增删查改
2.1 尾插和尾删
| void push_back(const value_type & val); |
| void push_back(value_type && val); |
| void pop_back(); |
void test02()
{// 尾插vector<int> v1;v1.push_back(1);v1.push_back(9);v1.push_back(4);v1.push_back(5);v1.push_back(1);for (auto& e : v1){cout << e << " ";}cout << endl;// 尾删v1.pop_back();v1.pop_back();for (auto& e : v1){cout << e << " ";}cout << endl;
}2.2 任意位置插入和删除
2.2.1 insert
表中是insert常见的接口:
| 指定位置插入val | iterator insert (const_iterator position, const value_type& val); |
| 指定位置插入范围数据 | iterator insert (const_iterator position, iterator first, iterator last); |
| 指定位置插入初始化列表 | iterator insert (const_iterator position, initializer_list<value_type> il); |
常见接口的使用:
void test03()
{vector<int> v1({ 1,2,3,4,5,6,7,8,9,10 });// 指定位置插入valv1.insert(v1.begin() + 3, 9);v1.insert(v1.begin() + 6, 12);for (auto& e : v1){cout << e << " ";}cout << endl;// 指定位置插入范围数据vector<int> v2 = { 136,232,888 };v1.insert(v1.end(), v2.begin(), v2.end());for (auto& e : v1){cout << e << " ";}cout << endl;// 指定位置插入初始化列表v1.insert(v1.begin(), { 99,66,55,77,88 });for (auto& e : v1){cout << e << " ";}cout << endl;
}2.2.2 erase
表中是erase常见的接口:
| 删除指定位置元素 | iterator erase (const_iterator position); |
| 删除迭代区间元素 | iterator erase (const_iterator first, const_iterator last); |
常见接口的使用:
void test04()
{// 删除指定位置vector<int> v1({ 98,12,45,66,36,27,30,25 });v1.erase(v1.begin()); //头删v1.erase(v1.end() - 1); //尾删v1.erase(v1.begin() + 5); //任意位置删除for (auto& e : v1){cout << e << " ";}cout << endl;// 删除迭代区间vector<int> v2(v1);v2.erase(v2.begin() + 2, v2.begin() + 5);for (auto& e : v2){cout << e << " ";}cout << endl;// 在指定位置前插入值为val的元素,比如:66之前插入30,如果没有则不插入// 1. 先使用find查找3所在位置// 注意:vector没有提供find方法,如果要查找只能使用STL提供的全局findauto pos = find(v1.begin(), v1.end(), 66);if (pos != v1.end()){// 2. 在pos位置之前插入30v1.insert(pos, 30);}for (auto& e : v1){cout << e << " ";}cout << endl;
}2.2.3 swap
交换两个vector的数据,在string的模拟实现operator=的优化版本则是利用swap,同理vector的模拟实现也可以这样使用。
| void swap (vector& x); |
2.2.4 operator[ ]
注意:这里返回的对应元素的引用
| reference operator[] (size_type n); |
| const_reference operator[] (size_type n) const; |
void test05()
{vector<int> v1({ 98,12,45,66,36,27,30,25 });// 获取指定位置的元素for (size_t i = 0; i < v1.size(); i++){cout << v1[i] << " ";}cout << endl;
}2.2.5 assign
assign的主要功能是:为字符串分配一个新值,替换其当前内容。
| 用n个val替换 | void assign (size_type n, const value_type& val); |
| 用初始化列表数据替换 | void assign (initializer_list<value_type> il); |
| 用迭代区间的数据替换 | void assign (iterator first, iterator last); |
void test06()
{vector<int> v1({ 98,12,45,66,36,27,30,25 });v1.assign(10, 1);for (size_t i = 0; i < v1.size(); i++){cout << v1[i] << " ";}cout << endl;v1.assign({ 99,88,77,33,55 });for (size_t i = 0; i < v1.size(); i++){cout << v1[i] << " ";}cout << endl;vector<int> v2 = { 136,232,888 };v1.assign(v2.begin(), v2.end());for (size_t i = 0; i < v1.size(); i++){cout << v1[i] << " ";}cout << endl;
}3. vector的容量
3.1 size 和 capacity
size:返回有效元素的个数
capacity:返回空间的大小
| size_t size(); |
| size_t capacity(); |
void test07()
{vector<int> v1({ 98,12,45,66,36,27,30,25 });cout << v1.size() << endl;cout << v1.capacity() << endl;v1.insert(v1.begin(), 10);v1.insert(v1.begin() + 5, 15);cout << v1.size() << endl;cout << v1.capacity() << endl;
}3.2 resize 和 reserve
resize():将有效字符的个数变成n个,多出的空间用字符c填充。
reserve():开辟指定大小的空间,当n<size()时,reserver不会改变容量大小。
| void resize (size_type n, value_type val = value_type()); |
| void reserve (size_type n); |
void test08()
{vector<int> v;for (int i = 1; i < 10; i++)v.push_back(i);v.resize(5);v.resize(8, 100);v.resize(12);cout << "v contains:";for (size_t i = 0; i < v.size(); i++)cout << ' ' << v[i];cout << '\n';
}3.3 vecctor扩容分析
在vs的环境,记录初始空间的大小,不断插入数据记录是否扩容。
void test09()
{vector<int> v;size_t n;n = v.capacity();cout << "making bar grow:\n" << endl;for (int i = 0; i < 50; i++){v.push_back(i);if (n != v.capacity()){n = v.capacity();// 扩容cout << "capacity changed: " << n << '\n';}}
}根据增长的趋势,可以发现在vs环境下,内存扩容大概是以1.5倍增长的!

在linux的环境下,内容扩容趋势大概是以2倍增长的。

4. 迭代器
begin和end:返回指向第一个元素的指针,最后一个元素的下一个位置的指针;
rbegin和rend:获取最后一个数据位置的指针,获取第一个数据前以个位置的指针
void test10()
{vector<int> v1({ 98,12,45,66,36,27,30,25 });// 利用迭代器遍历vector<int>::iterator it = v1.begin();while (it != v1.end()){cout << (*it) << " ";it++;}cout << endl;// 范围for -- 底层就是迭代器for (auto e : v1){cout << e << " ";}cout << endl;// for循环for (size_t i = 0; i < v1.size(); i++){cout << v1[i] << " ";}cout << endl;// 使用反向迭代器进行遍历再打印// vector<int>::reverse_iterator rit = v.rbegin();auto rit = v1.rbegin();while (rit != v1.rend()){cout << *rit << " ";++rit;}cout << endl;
}迭代器失效将在模拟实现部分讲解!敬请期待~
