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 v1;
// 传值构造
vector v2(10, 1); // 初始化为10个1
vector v3(10); // 初始化为10个0(初始化的值由编译器决定)
// 初始化列表构造
vector v4({ 1,2,3,4,5,6,7,8,9,10 });
// 迭代器构造
vector v5(v4.begin() + 5, v4.end());
vector::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 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 v1({ 1,2,3,4,5,6,7,8,9,10 });
// 指定位置插入val
v1.insert(v1.begin() + 3, 9);
v1.insert(v1.begin() + 6, 12);
for (auto& e : v1)
{
cout << e << " ";
}
cout << endl;
// 指定位置插入范围数据
vector 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 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 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提供的全局find
auto pos = find(v1.begin(), v1.end(), 66);
if (pos != v1.end())
{
// 2. 在pos位置之前插入30
v1.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 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 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 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 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 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 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 v1({ 98,12,45,66,36,27,30,25 });
// 利用迭代器遍历
vector::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::reverse_iterator rit = v.rbegin();
auto rit = v1.rbegin();
while (rit != v1.rend())
{
cout << *rit << " ";
++rit;
}
cout << endl;
}
迭代器失效将在模拟实现部分讲解!敬请期待~
浙公网安备 33010602011771号