C++STL序列式容器——vector容器详解

news2025/1/21 0:58:07

在这里插入图片描述
纵有疾风起,人生不言弃。本文篇幅较长,如有错误请不吝赐教,感谢支持。

💬文章目录

    • 一.vector容器基本概念
    • 二.vector常用操作
      • ①vector构造函数
      • ②特性操作
      • ③元素操作
      • ④赋值操作
      • ⑤交换操作
      • ⑥比较操作
      • ⑦插入和删除操作

一.vector容器基本概念

vector的数据安排以及操作方式,与array非常相似,都是一片连续的储存空间,两者的唯一差别在于空间的运用的灵活性。

array是静态数组,一旦配置了空间就无法再改变,要换大一点或者小一点的空间,可以,一切琐碎得由自己来,首先配置一块新的空间,然后将旧空间的数据搬往新空间,再释放原来的空间。

vector是动态空间(动态数组),随着元素的加入,它的内部机制会自动扩充空间以容纳新元素。因此vector的运用对于内存的合理利用与运用的灵活性有很大的帮助,我们再也不必害怕空间不足而一开始就要求一个大块头的array了。

在这里插入图片描述

①vector的实现技术:
vector的实现技术,关键在于其对大小的控制以及重新配置时的数据移动效率,一旦vector旧空间满了,如果客户每新增一个元素,vector内部只是扩充一个元素的空间,实为不智,因为只要是扩充空间(不论多大),其步骤就是“配置新空间-数据移动-释放旧空间”的大工程,时间成本很高,所以为了降低空间配置时的速度成本,vector实际配置的大小可能比客户端需求大一些,以备将来可能的扩充,这边是容量的概念。换句话说,一个vector的容量永远大于或等于其大小,一旦容量等于大小,便是满载,下次再有新增元素,整个vector容器就得另觅居所(配置新空间-数据移动-释放旧空间)。
②vector迭代器:
vector维护一个线性空间,所以不论元素的型别如何,普通指针都可以作为vector的迭代器,因为vector迭代器所需要的操作行为,如operaroe*, operator->, operator++, operator–, operator+, operator-, operator+=, operator-=, 普通指针天生具备。vector支持随机存取,而普通指针正有着这样的能力。所以vector提供的是随机访问迭代器(Random Access Iterators).
③vector的数据结构:
vector所采用的数据结构非常简单,线性连续空间,它以两个迭代器_Myfirst和_Mylast分别指向配置得来的连续空间中目前已被使用的范围,并以迭代器_Myend指向整块连续内存空间的尾端。
④注意:

所谓动态增加大小,并不是在原空间之后续接新空间(因为无法保证原空间之后尚有可配置的空间),而是分配一块更大的内存空间,然后将原数据拷贝新空间,并释放原空间。因此,对vector的任何操作,一旦引起空间的重新配置,指向原vector的所有迭代器就都失效了。这是程序员容易犯的一个错误,务必小心。

二.vector常用操作

①vector构造函数

注:使用vector容器时,需包含头文件#include < vector>

函数解释
vector< T > v;采用模板实现类实现(显示实例化),默认构造函数,
vector(v.begin(), v.end());将v[begin(), end())区间中的元素拷贝给本身
vector(n, elem);构造函数将n个elem拷贝给本身。
vector(const vector &vec);拷贝构造函数,拿另一个vector对象初始化本身

实例:vector构造函数

#include <iostream> 
#include<vector> 
using namespace std;
void printvector(const vector<int>& vec)
{
    for (vector<int>::const_iterator it = vec.begin(); it != vec.end(); ++it)
    {
        cout << *it;
    }
    cout << endl;
}
int main()
{
    vector<int> v1 = { 1,2,3 };//采用模板实现类实现(显示实例化),默认构造函数,
    vector<int> v2(6,1);//构造函数将n个elem拷贝给本身。
    int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };
    vector<int> v3(arr, arr+sizeof(arr)/ sizeof(arr[0]));//将v[begin(), end())区间中的元素拷贝给本身
    vector<int> v4(v1);//拷贝构造函数,拿另一个vector对象初始化本身
    printvector(v1);
    printvector(v2);
    printvector(v3);
    printvector(v4);
    return 0;
}

在这里插入图片描述

②特性操作

函数原型解释
size_t max_size() const;返回容器的最大长度
size_t capacity() const;返回容器的容量。
size_t size() const;返回容器的实际大小(已使用的空间)。
bool empty() const;判断容器是否为空。
void clear();清空容器。
void reserve(size_t size);容器预留size个元素长度,预留位置不初始化,元素不可访问,作用:预开辟空间,避免多次重新分配空间
void shrink_to_fit();将容器的容量降到实际大小(需要重新分配内存)。
void resize(size_t size);把容器的实际大小置为size,如果size<实际大小,会截断多出的部分;如果size>实际大小,则以默认值0填充新位置
void resize(size_t size,const T &value);把容器的实际大小置为size,如果size<实际大小,会截断多出的部分;如果size>实际大小,就用value填充。

实例:reserve和resize辨析:

#include <iostream> 
#include<vector> 
using namespace std;
void printVector(const vector<int>& vec)//形参使用const,避免被修改
{   //const_iterator只读迭代器
	for (vector<int>::const_iterator it = vec.begin(); it != vec.end(); ++it)
	{
		cout << *it;
	}
	cout << endl;
}
void test()
{
    //1.resize开辟空间,并初始化
	//2.reserve开辟空间,但不初始化

	vector<int> v2;
	v2.push_back(1);//尾部插入一个元素
	v2.push_back(2);
	v2.push_back(3);

	cout << "size:" << v2.size() << endl;
	v2.resize(5);//重新指定容器的长度为num,若容器变长,则以默认值填充新位置。
	cout << "size:" << v2.size() << endl;
	printvector(v2);
	v2.resize(2);//如果容器变短,则末尾超出容器长度的元素被删除。
	cout << "size:" << v2.size() << endl;
	printvector(v2);
	v2.resize(5,6);//如果容器变长,也可以用value填充
	cout << "size:" << v2.size() << endl;
	printvector(v2);

	v2.reserve(20);
	v2.push_back(20);
	printvector(v2);//容器变长了,但并没有初始化
	cout << "size:" << v2.size() << endl;
	cout << "capacity:" << v2.capacity() << endl;

	//cout << v2[10] << endl;//err,不能访问未初始化的空间
}
int main()
{
	test();
	return 0;
}

在这里插入图片描述

reserve作用:预开辟空间,避免多次重新分配空间
如果不加reserve预开辟空间,我们看看会重新分配多少次空间。

#include <iostream> 
#include<vector> 
using namespace std;
void test()
{
    vector<int> v;
	int* p = NULL;
	int num = 0;

	for (int i = 0; i < 10001000; i++)
	{
		v.push_back(i);
		if (p != &v[0])
		{
			p = &v[0];
			num++;
		}
	}
	cout << "num=" << num << endl;
	return 0;
}
int main()
{
	test();
	return 0;
}

在这里插入图片描述
加上v.reserve(10001000);
在这里插入图片描述

③元素操作

函数原型解释
T &operator[](size_t n);通过[]访问元素,如果越界,不抛异常,程序直接挂掉
T &at(size_t n);通过at方法获取下标为n的元素,如果n越界,抛出out_of_range异常
T *data();返回容器中动态数组的首地址。
const T *data() const;返回容器中动态数组的首地址。
T &front();返回第一个元素。
T &back();返回,最后一个元素。

④赋值操作

作用:通过重载赋值运算符operator=和成员函数assign(),给已存在的容器赋值,将覆盖容器中原有的内容。

函数原型解释
vector &operator=(const vector &v);把容器v赋值给当前容器。
assign(beg, end);将[beg, end)区间中的数据拷贝赋值给本身。
void assign(const size_t n, const T& value); ;将n个value拷贝赋值给本身。
void assign(const size_t n, const T& value);把n个value给容器赋值。

⑤交换操作

💬表格一览:

函数原型解释
void swap(vector &v);把当前容器与v交换。交换的是动态数组的地址。作品:收缩内存空间。

swap妙用:收缩内存空间

#include <iostream> 
#include<vector> 
using namespace std;
void test()
{
    vector<int> v;
	for (int i = 0; i < 100000; i++)
	{
		v.push_back(i);
	}

	cout << "v的容量:" << v.capacity() << endl;
	cout << "v的实际大小:" << v.size() << endl;
	cout << "----------------" << endl;

	v.resize(10);//将容器的实际大小设置为10,但容量没变
	cout << "resize后v的容量:" << v.capacity() << endl;
	cout << "resize后v的实际大小:" << v.size() << endl;
	cout << "----------------" << endl;

	vector<int>(v).swap(v);//匿名对象和v对象交换
	//匿名对象调用拷贝构造,匿名对象的容量和实际大小均为10,此时在与v进行交换,做到了收缩内存的目的
	cout << "与匿名对象交换后v的容量:" << v.capacity() << endl;
	cout << "与匿名对象交换后v的实际大小:" << v.size() << endl;
}
int main()
{
	test();
	return 0;
}

在这里插入图片描述

⑥比较操作

💬表格一览:

函数原型解释
bool operator == (const vector< T > & v) const;
bool operator != (const vector< T > & v) const;

⑦插入和删除操作

💬表格一览:

函数原型解释
iterator insert(iterator pos, const T& ele);在指定位置插入一个元素ele 返回指向插入元素的迭代器。
iterator insert(const_iterator pos, int count,ele);迭代器指向位置pos插入count个元素ele.返回指向插入元素的迭代器。
void push_back(const T& ele);尾部插入元素ele
void pop_back();删除最后一个元素
iterator erase(const_iterator start, const_iterator end);删除迭代器从start到end之间的元素,返回下一个有效的迭代器。
iterator erase(const_iterator pos);删除迭代器指向的元素,返回下一个有效的迭代器。

实例:vector插入和删除操作

#include <iostream> 
#include<vector> 
using namespace std;
void printVector(const vector<int>& vec)//形参使用const,避免被修改
{   //const_iterator只读迭代器
	for (vector<int>::const_iterator it = vec.begin(); it != vec.end(); ++it)
	{
		cout << *it;
	}
	cout << endl;
}
void test()
{
    vector<int> v;
	for (int i = 0; i < 5; i++)
	{
		v.push_back(i + 1);//尾部插入元素
	}

	printVector(v);//1 2 3 4 5

	v.insert(v.begin() + 1, 2, 100);//在第二个元素前插入2个100
	printVector(v);//1 100 100 2 3 4 5

	v.pop_back();//尾部删除一个元素
	printVector(v);//1 100 100 2 3 4
	cout << "-------------" << endl;
	v.erase(v.begin());//删除第一个元素
	printVector(v);//100 100 2 3 4

	vector<int>::const_iterator it=v.erase(v.begin() + 1, v.end() - 1);//删除从第二个元素到倒数第二个元素,返回下一个有效迭代器
	printVector(v);//100 4

	v.insert(it, 66);
	printVector(v);//100 66 4
}
int main()
{
    test();
	return 0;
}

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/813130.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

MATLAB编程实践12、13

生命游戏 游戏的宇宙是无限可扩展的二维矩形网格&#xff0c;群体是那些标注为存活的网格的集合。群体可以依照称为代的离散时间步距进化。在每一步中&#xff0c;每个网格的命运由它周围最近的8个网格邻居的活度决定&#xff0c;规则如下&#xff1a; 如果一个存活的网格有两个…

想阻止BOT攻击?一起聚焦灵活有效的F5解决方案

伴随着突如其来的数字创新&#xff0c;使潜在的欺诈无处不在。现在&#xff0c;帮我们查找机票交易、位置理想的演唱会座位的 BOT技术正在为网络犯罪分子所利用。权威数据表示&#xff0c;在过去5年&#xff0c;撞库攻击已成为造成经济损失的最大原因之一&#xff0c;几乎每个企…

小研究 - 基于解析树的 Java Web 灰盒模糊测试(二)

由于 Java Web 应用业务场景复杂, 且对输入数据的结构有效性要求较高, 现有的测试方法和工具在测试Java Web 时存在测试用例的有效率较低的问题. 为了解决上述问题, 本文提出了基于解析树的 Java Web 应用灰盒模糊测试方法. 首先为 Java Web 应用程序的输入数据包进行语法建模创…

前端技术周刊 2023-07-30:Promise.withResolvers 进入 Stage3

项目地址&#xff1a;olivewind/weekly[1] 微信公众号&#xff1a;依赖注入 发布时间&#xff1a;2023.07.30 本周内容&#xff1a;资讯x2、开源x8、文章x4 动态 Promise.withResolvers 进入 Stage3 某些情况下需要在 Promise 外部获取 resolve 和 reject 句柄&#xff0c;我们…

【云原生】一文学会Docker存储所有特性

目录 1.Volumes 1.Volumes使用场景 2.持久将资源存放 3. 只读挂载 2.Bind mount Bind mounts使用场景 3.tmpfs mounts使用场景 4.Bind mounts和Volumes行为上的差异 5.docker file将存储内置到镜像中 6.volumes管理 1.查看存储卷 2.删除存储卷 3.查看存储卷的详细信息…

RWEQ模型参量提取

土壤风蚀是一个全球性的环境问题。中国是世界上受土壤风蚀危害最严重的国家之一&#xff0c;土壤风蚀是中国干旱、半干旱及部分湿润地区土地荒漠化的首要过程。中国风蚀荒漠化面积达160.74104km2&#xff0c;占国土总面积的16.7%&#xff0c;严重影响这些地区的资源开发和社会经…

机器学习深度学习——Dropout

&#x1f468;‍&#x1f393;作者简介&#xff1a;一位即将上大四&#xff0c;正专攻机器学习的保研er &#x1f30c;上期文章&#xff1a;机器学习&&深度学习——权重衰减 &#x1f4da;订阅专栏&#xff1a;机器学习&&深度学习 希望文章对你们有所帮助 Drop…

【MTI 6.S081 Lab】traps

【MTI 6.S081 Lab】traps RISC-V assembly (easy)Backtrace (moderate)实验任务Hints解决方案backtracesys_sleep Alarm (hard)实验任务test0: invoke handlerHint test1()/test2()/test3(): resume interrupted codeHints 解决方案trap.c中的时钟中断处理程序sys_sigalarmsys_…

大促之前全链路压测监控

1. skywalking服务监控 1.1 skywalking简介 Skywalking 是一个APM系统&#xff0c;即应用性能监控系统&#xff0c;为微服务架构和云原生架构系统设计 它通过探针自动收集所需的指标&#xff0c;并进行分布式追踪&#xff0c;通过这些调用链路以及指标&#xff0c;Skywalking …

使用Postman如何在接口测试前将请求的参数进行自定义处理

1、前言 当我们使用 Postman 进行接口测试时&#xff0c;对于简单的不需要处理的接口&#xff0c;直接请求即可&#xff0c;但是对于需要处理的接口&#xff0c;如需要转码、替换值等&#xff0c;则就麻烦一些&#xff0c;一般我们都是先手动把修改好的值拷贝到请求里再进行请…

计算机的大小端模式

计算机的大小端模式 大端/小端字节序字节序转换函数判断Linux字节序的方法string有字节序的说法吗64位系统和32位系统的区别 大端/小端字节序 计算机硬件有两种储存数据的方式&#xff1a;大端字节序&#xff08;big endian&#xff09;和小端字节序&#xff08;little endian…

MySQL数据库——DQL操作——基本查询

文章目录 前言事前准备——测试数据整表查询指定列查找别名查询MySQL运算符条件查询模糊查询排序查询聚合查询分组查询分组之后的条件筛选 分页查询将整张表的数据插入到另一张表中 前言 MySQL数据库常见的操作是增删查改&#xff0c;而其中数据的查询是使用最多&#xff0c;也…

玩转LaTeX(三)【数学公式(基础)、​矩阵、多行公式】

数学公式基础 导言区&#xff08;引包&#xff09; \usepackage{amsmath} %带星号的eqution 正文区 \begin{document}%数学公式初步 \section{简介} \LaTeX{}将排版内容分为文本模式和数学模式。文本模式用于普通文本排版&#xff0c;数学模式用于数学公式排版。 …

小白带你学习linux的mysql服务(主从mysql服务和读写分离三十一)

目录 二、MySQL Replication优点&#xff1a; 三、MySQL复制类型 1、异步复制&#xff08;Asynchronous repication&#xff09; 2、全同步复制&#xff08;Fully synchronous replication&#xff09; 3、半同步复制&#xff08;Semisynchronous replication&#xff09;…

用pip给python安装第三方包

2023年7月30日&#xff0c;周日晚上 目录 搜索包安装包升级包卸载包查看安装了哪些包查看指定的包的详细信息查看pip把某个包安装到了哪里 搜索包 现在只能去专门的网站搜索python的第三方包了 Search results PyPI 安装包 通过下面这条指令就可以安装包 pip install pac…

【数据分享】1999—2021年地级市工业企业资产情况和主要财务指标(Excel/Shp格式)

在之前的文章中&#xff0c;我们分享过基于2000-2022年《中国城市统计年鉴》整理的1999-2021年地级市的人口相关数据、各类用地面积数据、污染物排放和环境治理相关数据、房地产投资情况和商品房销售面积、社会消费品零售总额和年末金融机构存贷款余额、地方一般公共预算收支状…

Prometheus中的关键设计

1、标准先行&#xff0c;注重生态 Prometheus 最重要的规范就是指标命名方式&#xff0c;数据格式简单易读。比如&#xff0c;对于应用层面的监控&#xff0c;可以要求必须具备这几个信息。 指标名称 metric Prometheus 内置建立的规范就是叫 metric&#xff08;即 __name__…

RedLock + Redisson

目录 2.9 RedLock2.9.1 上述实现的分布式锁在集群状态下失效的原因2.9.2 解决方式-RedLock 2.10 redisson中的分布式锁简单使用redisson中的锁Redisson常用配置2.10.1 Redisson可重入锁实现原理2.10.2 公平锁&#xff08;Fair Lock&#xff09; 2.9 RedLock 2.9.1 上述实现的分…

FLinkCDC读取MySQl时间戳时区相关问题解决汇总

FlinkCDC时间问题timestamp等https://blog.csdn.net/qq_30529079/article/details/127809317 FLinkCDC读取MySQl中的日期问题https://blog.csdn.net/YPeiQi/article/details/130265653 关于flink1.11 flink sql使用cdc时区差8小时问题https://blog.csdn.net/weixin_44762298/…

Redis以及Java使用Redis

一、Redis的安装 Redis是一个基于内存的 key-value 结构数据库。 基于内存存储&#xff0c;读写性能高 适合存储热点数据&#xff08;热点商品、资讯、新闻&#xff09; 企业应用广泛 官网&#xff1a;https://redis.io 中文网&#xff1a;https://www.redis.net.cn/ Redis…