C++ vector 学习笔记
作者:@cherish.
课程学习内容为作者从学校的PPT处摘抄,仅供自己学习参考,若需转载请注明出处:https://www.cnblogs.com/cherish-/p/16148092.html
std::vector
以下内容大多来自此处,并将其中内容做了简化,想详细了解的可点击该链接进行了解和学习。
定义于头文件<vector>
std::vector
是封装动态数组的顺序容器。连续存储元素,所以不仅可以通过迭代器,还能用指向元素的常规指针访问元素。
vector
的存储是自动管理的,因为要分配更多内存以管理将来的增长,所以通常占用多于静态数组的空间。扩容只在额外内存耗尽时重分配。分配的内存总量可用capacity()
函数查询。可以通过调用shrink_to_fit()
返回多出的内存给系统。若元素数量已知,则reserve()
函数可用于消除重分配。
vector
里面有一个指针指向一片连续的空间,当空间装不下的时候,会申请一片更大的空间,将原来的数据拷贝过去,并释放原来的旧空间。vector
在动态增加大小的时候,不是在原有的空间上持续新的空间(无法保证原空间的后面还有可供配置的空间),而是以原大小的两倍另外配置一块较大的空间,然后将原内容拷贝过来,并释放原空间。在VS
下是1.5
倍扩容,在GCC
下是2
倍扩容。
vector
的常见操作复杂度如下:
- 随机访问:
- 在末尾插入或移除元素:均摊
- 插入或移除元素:(与到
vector
结尾的距离呈线性关系)
vector
的初始化方式(以int类型为例)
-
不带参数的构造函数初始化
std::vector<int>a;//初始化一个vector对象a,其大小为0
-
带参数的构造函数初始化
std::vector<int>a(10);//初始化一个vector对象a,其大小为10,初始值为默认值 std::vector<int>a(10 , 1);//初始化一个vector对象a,其大小为10,初始值为1
-
通过已有数组进行初始化
int arr[] = {0 , 1 , 2 , 3 , 4 , 5};//定义一个大小为6的数组arr std::vector<int>a(arr + 1 , arr + 6);//初始化一个vector对象a,其大小为5,其初始值为{1 , 2 , 3 , 4 , 5},注意,这里的区间是左闭右开的
-
通过已有
vector
进行初始化std::vector<int> b = {1 , 2 , 3 ,4};//初始化一个vector对象,其初始值为{1 , 2 , 3 ,4} std::vector<int>a(b);//定义一个vector对象,并用b进行初始化 //考虑上一个方法,此方法等价于 std::vector<int>a(b.begin() , b.end());
vector
的赋值方式
std::vector<int>b = {1 , 2 , 3 , 4};//初始化一个vector对象,初始值为{1 , 2 , 3 , 4}
std::vector<int>a = b;//定义一个vector对象a并将b的值赋值给a
//假设已有对象a,可通过下述方式进行修改
a = std::vector<int>(10 , 0);//此时a的元素由{1 , 2 , 3 , 4}变成10个0
a.assign(10 , 0);//等价于上一条语句
多维vector
定义
using std::vector;//在没有使用using namespace std时,使用该语句可以在声明vector时不用加前面的std::
vector<vector<int>>a;//定义一个二维的vector对象,其大小为0
vector<vector<int>>b(10);//定义一个二维的vector对象,其大小为10,每行是一vector对象,其大小为0
vector<vector<int>>c(10 , vector<int>(10 , 0));//定义一个二维vector对象,其行和列的初始大小都为10
//更高维依次类推即可
成员函数
元素访问
-
at(size_type pos)
返回位于指定位置
pos
的元素的引用,有边界检查。若pos
不在容器范围内,则抛出std::out_of_range
类型的异常,例如:a.at(1);//返回2对应的引用 a.at(3);//返回4对应的引用 a.at(5);//抛出越界异常
-
operator[]
返回位于指定位置
pos
的元素的引用,不进行边界检查,可以类比定义的数组直接使用下标的方式进行访问。a[1];//结果同上 a[5];//发送越界异常
-
front()
返回容器首元素的引用,在空容器上使用
front()
是未定义行为。a.fornt();//返回1对应的引用
-
back()
返回容器尾元素的引用,在空容器上使用
back()
是未定义行为。a.back();//返回5对应的引用
以上函数的访问效率都是的。
容量
以下函数以std::vector<int> a = {1 , 2 , 3 , 4 , 5};
为例
-
empty()
检查容器是否无元素,即
begin() == end()
a.empty();//调用方式
-
size()
返回容器中的元素数量。注意:此方法返回的是无符号整数,使用过程中进行
-1
操作时注意是否产生溢出。a.size();//返回5
-
max_size()
返回根据系统或库实现限制的容器可保有的元素最大数量。通常反映容器大小的理论极限。
以上函数的访问效率都是的。
迭代器
以下函数以std::vector<int> a = {1 , 2 , 3 , 4 , 5};
为例
-
begin()/cbegin()
返回指向
vector
首元素的迭代器。若vector
大小为,则返回的迭代器等于end()
a.begin();//指向1的迭代器 //想要得到1这个值可以使用如下方法 *a.begin();
-
end()/cend()
返回指向
vector
末元素后一元素的迭代器。此元素表现为占位符不能使用*a.end()
去访问其元素值。 -
rbegin()/crbegin()
返回指向逆向
vector
首元素的迭代器。a.rbegin();//指向5的迭代器 *a.rbegin();//该迭代器的值
-
rend()/crend()
返回指向逆向
vector
尾元素的后一个元素,也是占位符。
以上函数的访问效率都是的。
其他成员函数
-
clear()
清除容器中的所有元素。调用该方法后
size()
的返回值为。注意:此方法保持vector
的capacity()
不变。即:int sizePre = sizeof(a);//清除前的vector的大小 a.clear();//调用clear() int sizeNext = sizeof(a); sizePre == sizeNext;//此表达式的值为true
虽然原有的空间还在,但使用下标去访问非法。
-
insert()
该函数有好几个重载,可以参考此处进行学习
复杂度是线性的。
-
erase()
有两个重载,分别是移除位于
pos
的元素和移除范围[first , last)
中的元素。具体可参考此处进行学习
复杂度也是线性的。
-
push_back()
将给定元素添加到容器末尾。
-
emplace_back()
在容器尾就地构造元素。就平时使用而言与
push_back()
方法没区别。 -
pop_back()
移除末尾的元素。
-
resize()
改变容器中可存储元素的个数。可以参考此处学习
-
swap(vector& other)
将内容与
other
的交换。不在单独的元素上调用任何移动、复制或交换操作。所有迭代器和引用保持合法。尾后迭代器被非法化。复杂度是的。调用
std::swap(a , b)
进行交换,在c++98
的复杂度是线性的,在c++11
中对该函数进行了特化,std::swap(vector& lhs , vector& rhs)
等价于lhs.swap(rhs)
,复杂度。
使用一些algorithm库函数
以下内容使用vector<int>a = {1 , 2 , 3 , 3 , 4 ,5 , 8 , 7 , 9}
为例。
-
快速排序
sort
std::sort(a.begin() , a.end());//将区间[0 , 9)的元素排序 std::sort(a.begin() + 1 , a.end());//将区间[1 , 9)的元素排序 std::sort(a.begin() + 1 , a.begin() + 5);//将区间[1 , 5)的元素排序
-
lower_bound
该函数返回第一个大于等于
target
的元素的迭代器,使用该函数前数组要有序。std::lower_bound(a.begin() , a.end() , target);//返回对应的迭代器,若没有大于等于target的元素则返回a.end() int idx = std::lower_bound(a.begin() , a.end() , target) - a.begin();//返回该迭代器对应的元素的下标
-
upper_bound
该函数返回第一个大于
target
的元素的迭代器,使用该珊瑚前数组要有序。std::upper_bound(a.begin() , a.end() , target);//返回对应的迭代器,若没有大于target的元素则返回a.end() int idx = std::upper_bound(a.begin() , a.end() , target) - a.begin();//返回该迭代器对应的元素的下标
-
去重
将数组中的重复元素去除,本质是将重复的元素放在数组末尾。去重前数组要有序。
std::sort(a.begin() , a.end());//先排序 int n = std::unique(a.begin() , a.end()) - a.begin();//n我去重后的元素数量 //使用上述语句后,a = {1 , 2 , 3 , 4 , 7 , 8 , 9 , 3} n = 7
作者:cherish.
出处:https://home.cnblogs.com/u/cherish-/
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· PowerShell开发游戏 · 打蜜蜂
· 在鹅厂做java开发是什么体验
· 百万级群聊的设计实践
· WPF到Web的无缝过渡:英雄联盟客户端的OpenSilver迁移实战
· 永远不要相信用户的输入:从 SQL 注入攻防看输入验证的重要性