C++初阶:STL详解(三)——vector的介绍和使用
✨✨小新课堂开课了,欢迎欢迎~✨✨
🎈🎈养成好习惯,先赞后看哦~🎈🎈
所属专栏:C++:由浅入深篇
小新的主页:编程版小新-CSDN博客
前言:
前面我们刚刚了解了string类的使用和模拟实现,当对string有了一定的了解后,再来看vector的使用和后面要提到模拟实现是很好上手的。
C++初阶:STL详解(一)——string类-CSDN博客
C++初阶:string类的模拟实现-CSDN博客
一.什么是vector?
vector(向量)是C++标准库中的一种序列容器,它是一种非常常用的动态数组实现。可以高效的存储和访问一组相同类型的元素,能够自动管理储存,可动态增长或收缩。
vector是一个模板类,定义在头文件(include<vector>)中,可以使用vector来存储和访问任意类型的对象。
二.vector的特性
1.动态数组:可以动态地增加和减少数组元素,自动管理内存分配和释放,不需要手动进行内存操作。
2.高效随机访问:支持随机访问
3.连续存储:元素在内存中连续存储
4.支持插入和删除:在尾部或头部插入和删除元素通常是高效的,但是其他位置的效率较低。
5.丰富的接口:提供了多种成员函数,如push_back,pop_back,insert,erase等,方便进行各种操作。
三.vector的文档介绍
vector - C++ Reference(英文版)
std::vector - cppreference.com(中文版)
四.vector的使用
4.1vector的定义
(constructor)构造函数声明 | 接口说明 |
vector()(重点) | 无参构造 |
vector(size_type n, const value_type& val = value_type()) | 构造并初始化n个val |
vector (const vector& x); (重点) | 拷贝构造 |
vector (InputIterator first, InputIterator last); | 使用迭代器进行初始化构造 |
1.vector(): 构造一个空vector
vector<int> v1;//构造一个int 类型的空容器
2.vector(size_type n, const value_type& val = value_type()):构造一个vector,元素个数为n,元素为value_type()
vector<int> v2(10, 1);//构造一个含有10个1的int类型容器
vector<char> v5(10, 'c'); //构造一个含有10个c的char类型容器
3. vector (const vector& x) :拷贝构造
vector<int> v3(v2);//拷贝构造
4.vector (InputIterator first, InputIterator last) :使用迭代器区间进行初始化构造
vector<int> v4(v2.begin(), v2.end());//使用迭代器区间拷贝构造v2容器的一部分
4.2vector的空间增长问题
容量空间 | 接口说明 |
size | 获取数据个数 |
capacity | 获取容量大小 |
empty | 判断是否为空 |
resize(重点) | 改变vector的size |
reserve (重点) | 改变vector的capacity |
size和capacity
void vector2()
{
vector<int> v1(10, 1);
cout << "size:" << v1.size() << endl;//获取当前容器有效元素的个数
cout << "capacity:" << v1.capacity() << endl;//获取当前容器的容量大小
}
运行结果:
小扩展:
我们在说string类的时候,也提到过。capacity的代码在vs和g++下分别运行会发现,vs下capacity是按1.5倍增长的,g++是2倍增长的。这个问题经常会考察,不要固化的认为,vector增容都是2倍,具体增长多少根据具体的需求定义的。vs是PJ版本STL,g++是SGI版本STL。
empty
用于判断当前容器是否为空,true:返回非0(一般是1):;false:返回0。
void vector2()
{
vector<int> v1(10, 1);
cout << v1.empty() << endl;
}
运行结果:0
resize和reserve
resize函数改变容器中的有效元素个数,reserse函数改变容器的容量。
resize规则:
1、当所给值大于容当前容器的size时,将size扩大到该值,扩大的元素为第二个所给值,若未给出,则int型默认为0,char型默认是'\0'。
2、当所给值小于容器当前的size时,将size缩小到该值。
reserve规则:
1、当所给值大于当前容器的capacity时,将capacity扩大到该值。
2、当所给值小于当前容器的capacity时,什么也不做,不会缩容。
void vector2()
{
vector<int> v(10, 1);
cout << "size:" << v.size() << endl;
cout << "capacity:" << v.capacity() << endl;
v.reserve(20);//改变当前容器的容量为20
cout << "size:" << v.size() << endl;
cout << "capacity:" << v.capacity() << endl;
v.resize(5);//改变当前容器的size为5
cout << "size:" << v.size() << endl;
cout << "capacity:" << v.capacity() << endl;
}
运行结果:
注意:reserve只负责开辟空间,如果确定知道需要用多少空间,reserve可以缓解vector增容的代价缺陷问题。resize在开空间的同时还会进行初始化,影响size。
4.3vector迭代器的使用
iterator的使用 | 接口说明 |
begin + end(重点) | begin获取第一个数据位置的iterator/const_iterator, end获取最后一个数据的下一个位置的iterator/const_iterator |
rbegin + rend | rbegin获取最后一个数据位置的reverse_iterator,rend获取第一个数据前一个位置的reverse_iterator |
void vector3()
{
int arr[] = { 1,2,3,4,5,6,7,8,9 };
vector<int> v(begin(arr), end(arr));//C++11将一个整形数组装换为vector
//正向迭代器进行遍历
cout << "正向迭代器遍历:";
vector<int>:: iterator it = v.begin();
while (it != v.end())
{
cout << *it << " ";
it++;
}
cout << endl;
//反向迭代器遍历
cout << "反向迭代器遍历:";
vector<int>::reverse_iterator rit = v.rbegin();
while (rit != v.rend())
{
cout << *rit << " ";
rit++;
}
cout << endl;
}
运行结果:
除了上面遍历的方式,我们知道支持迭代器就支持范围for,因此我们也可以使用范围for对容器进行遍历。
void vector3()
{
int arr[] = { 1,2,3,4,5,6,7,8,9 };
vector<int> v(begin(arr), end(arr));//C++11将一个整形数组装换为vector
for (auto ch : v)
{
cout << ch << " ";
}
}
运行结果:
4.4vector的增删查改
vector增删查改 | 接口说明 |
push_back(重点) | 尾插 |
pop_back (重点) | 尾删 |
find | 查找。(注意这个是算法模块实现,不是vector的成员接口) |
insert | 在position之前插入val |
erase | 删除position位置的数据 |
swap | 交换两个vector的数据空间 |
operator[] (重点) | 像数组一样访问 |
push_back 和 pop_back
void vector4()
{
vector<int> v;
v.push_back(1);//尾插
v.push_back(2);
v.push_back(3);
v.push_back(4);
v.pop_back();//尾删
vector<int>::iterator it = v.begin();
while (it != v.end())
{
cout << *it << " ";
it++;
}
}
运行结果:
find
find: template <class InputIterator, class T> InputIterator find (InputIterator first, InputIterator last, const T& val)
find函数有三个参数,前两个参数确定了一个迭代器区间(左闭右开),第三个参数确定所要寻找的值。find函数在所给迭代器区间寻找第一个匹配的元素,并返回它的迭代器,若未找到,则返回所给的第二个参数。
insert和erase
void vector4()
{
vector<int> v;
v.push_back(1);//尾插
v.push_back(2);
v.push_back(3);
v.push_back(4);
vector<int>:: iterator pos = find(v.begin(), v.end(), 3);//返回元素为3位置的迭代器
v.insert(pos, 8);//在pos位置插入一个8
pos = find(v.begin(), v.end(), 4);
v.erase(pos);//删除pos位置的元素
vector<int>::iterator it = v.begin();
while (it != v.end())
{
cout << *it << " ";
it++;
}
cout << endl;
}
运行结果:
swap
swap函数可以交换两个容器的数据空间,实现两个容器的交换。
void vector5()
{
vector<int> v1(10, 1);
vector<int> v2(5, 2);
cout << "交换前:" << endl;
cout << "v1:" << v1.size() <<" "<< v1.capacity() << endl;
cout << "v2:" << v2.size() <<" "<< v2.capacity() << endl;
swap(v1,v2);
cout << "交换后:" << endl;
cout << "v1:" << v1.size() <<" "<< v1.capacity() << endl;
cout << "v2:" << v2.size() << " "<<v2.capacity() << endl;
}
运行结果:
operator[]
vector当中实现了 [ ] 操作符的重载,因此我们也可以通过“下标+[ ]”的方式对容器当中的元素进行访问。当然也可以对其进行修改。
void vector6()
{
int arr[] = { 1,2,3,4,5,6,7,8,9 };
vector<int> v(begin(arr), end(arr));//C++11将一个整形数组装换为vector
for (int i = 0; i < v.size(); i++)
{
v[i] += 2;
cout << v[i] << " ";
}
cout << endl;
}
运行结果:
不知不觉中,我们就已经知道了四种遍历容器的方式了:下标+[]/正向迭代器/反向迭代器/范围for。
总结:
以上就是对vector及其常见接口的介绍,这里还有一个经典的迭代器失效的问题,我们后面讲,vector的难点在于模拟实现,这个放在迭代器失效问题之后也会讲。
感谢大家的观看,创作不易,还请各位大佬点赞支持~