【C++】vector的认识与使用

news2024/11/23 17:13:33

vector的认识与使用

  • 认识vector
  • vector的使用
    • Member functions(成员函数)
      • 构造函数(constructor)
      • 析构函数(destructor)
      • 赋值构造函数(operator=)
    • Iterators(迭代器)
      • begin
      • end
      • rbegin
      • rend
    • Capacity(容量)
      • size
      • max_size
      • resize
      • capacity
      • empty
      • reserve
    • Element access(元素访问)
      • operator[]
      • at
      • front
      • back
    • Modifiers(修饰符)
      • assign
      • push_back
      • pop_back
      • insert
      • erase
      • swap
      • clear

认识vector

vector:翻译过来是向量,矢量。但是学习过来,给我的感觉类似于顺序表,或者说是数组??

在这里插入图片描述

  • std::vector
  • template < class T, class Alloc = allocator > class vector; // generic template

在这里插入图片描述
class T代表的是一个类型,是成员变量。
在这里插入图片描述
allocator代表的是空间配置器。

  • vector是一个可以改变大小的代表数组的序列容器。
  • 类似于数组,vector使用连续的存储位置存储元素,意味着可以采用下标对vector的元素进行访问,并且和数组一样高效。但是不同于数组,其大小可以随着存储被容器自动处理而动态改变。
  • 本质来将,vector使用动态分配数组来存储它的元素。对于数组而言,当新元素被插入的时候,数组为了增加存储空间需要被重新分配大小。其做法是,分配一个新的数组,然后将全部元素移到这个数组。就时间而言,这是一个相对代价高的任务,vector并不会每次都重新分配大小。
  • vector分配空间策略:vector会分配一些额外的空间以适应可能的增长,因为存储空间比实际需要的存储空间更大。不同的库采用不同的策略权衡空间的使用和重新分配。但是无论如何,重新分配都应该是对数增长的间隔下进行增长的,以至于在末尾插入一个元素的时候可以提供摊销的恒定时间复杂度。
  • 因此,vector占用了更多的存储空间,为了获得管理存储空间的能力,并且以一种有效的方式动态增长。
  • 与其他动态序列容器相比(deque,list,forward_list),vector在访问元素的时候更加高效,在末尾添加和删除元素相对高效。对于其他不在末尾的删除和插入操作,效率更低。比起list和forward_list统一的迭代器和引用更好。

vector的使用

在使用STL的三个境界:能用,明理,能扩展。

在介绍vector的时候,需要结合文档来学习:链接: vector

Member functions(成员函数)

构造函数(constructor)

在这里插入图片描述

  • std::vector::vector
  • 构造vector
  • 构造一个vector容器,根据使用的构造函数版本初始化其内容
  • default (1)
    explicit vector (const allocator_type& alloc = allocator_type());
    无参构造函数(默认构造)
    构造一个没有任何元素的空的容器
	vector<int> v1;
  • fill (2)
    explicit vector (size_type n, const value_type& val = value_type(),
    const allocator_type& alloc = allocator_type());
    fill构造函数
    构造一个有n个元素的容器,每一个元素都是val的值。
	vector<int> v2(10, 1);
	vector<char> v3(5, 'x');
	vector<string> v4(6, "hello");
  • range (3)
    template < class InputIterator >
    vector (InputIterator first, InputIterator last,
    const allocator_type& alloc = allocator_type());
    range构造函数
    构造一个函数,其中包含与范围(first,last)一样长的元素,每一个元素以相同的顺序从该范围内的相应元素构造。
	int a[4] = { 4,27,22,20 };
	vector<int> v5(a, a + 4);

这种方式可以使用自己的迭代器进行构造:

	vector<int> v1(10, 1);
	vector<int> v2(v1.begin(), v1.end());

同时也可以使用其他容器的迭代器:

	string str("hello world");
	vector<char> v(str.begin(), str.end());

【说明】STL中包括容器(存储数据)和算法(对数据进行处理),在算法中有一个sort()函数,头文件为< algorithm >,就是使用迭代器进行排序的。
在这里插入图片描述
下面进行升序排序操作:

	int a[4] = { 4,27,22,20 };
	vector<int> v(a, a + 4);

	sort(v.begin(), v.end());
	for (size_t i = 0; i < v.size(); ++i)
	{
		cout << v[i] << " ";
	}
	cout << endl;

下面进行降序排序操作:

	int a[4] = { 4,27,22,20 };
	vector<int> v(a, a + 4);

	greater<int> g;
	sort(v.begin(), v.end(), g);
	for (size_t i = 0; i < v.size(); ++i)
	{
		cout << v[i] << " ";
	}
	cout << endl;

降序操作也可以写成匿名对象的方式:

	int a[4] = { 4,27,22,20 };
	vector<int> v(a, a + 4);

	sort(v.begin(), v.end(), greater<int>());
	for (size_t i = 0; i < v.size(); ++i)
	{
		cout << v[i] << " ";
	}
	cout << endl;

其他容器也是允许被排序的,例如string类,数组等等。

  • copy (4)
    vector (const vector& x);
    拷贝构造
    构造一个函数,其中包含x中的每一个元素的副本,顺序相同。
	vector<int> v6(10, 2);
	vector<int> v7(v6);

【注意】了解vector的基本原理之后,可以觉得vector已经可以代替string了,但是这是不可取的。

vector< char > 不能代替string的原因:
首先俩者是存在不同点的,string后面保证会出现’\0’,这是为了像C兼容,而vector是不会自动出现"\0"的,需要手动添加,而手动添加的代价就是难免会忘记。同时,string的接口是要比vector更加丰富的,很多关于string的专业接口函数。例如:vector的比较大小相较于string类的比较大小是没有意义的。

vector是针对所有类型的,同时vector也是可以引用string类的。

	vector<string> v;

可以向string类型的vector添加字符串:

	string name1("大柏");
	v.push_back(name1);

这里可以替换成匿名对象

	v.push_back(string("大柏"));

也可以直接添加字符串:

	v.push_back("大柏");

需要注意的是,这里直接添加字符串是相当于隐式类型转换,将字符串先进行拷贝构造,然后再进行构造,系统会直接优化成直接构造。

析构函数(destructor)

在这里插入图片描述

  • std::vector::~vector
  • ~vector();
  • 析构函数
  • 销毁容器对象

赋值构造函数(operator=)

在这里插入图片描述

  • std::vector::operator=
  • copy (1)
    vector& operator= (const vector& x);
  • 分配内容
	vector<int> v1(10, 5);
	vector<int> v2;
	v2 = v1;

Iterators(迭代器)

begin

在这里插入图片描述

  • std::vector::begin
  • iterator begin();
  • const_iterator begin() const;
  • 返回指向开始的迭代器

end

在这里插入图片描述

  • std::vector::end
  • iterator end();
  • const_iterator end() const;
  • 返回指向结尾的迭代器

【注意】迭代器无const可以进行读写,而有const只能进行度。

	vector<int> v(10, 5);
	vector<int>::iterator it = v.begin();
	while (it != v.end())
	{
		cout << *it << " ";
		++it;
	}
	cout << endl;

在这里插入图片描述

rbegin

在这里插入图片描述

  • std::vector::rend
  • reverse_iterator rend();
  • const_reverse_iterator rend() const;
  • 返回指向反向结尾(开头)的反向迭代器

rend

在这里插入图片描述

  • std::vector::rend
  • reverse_iterator rend();
  • const_reverse_iterator rend() const;
  • 返回指向反向开头(结尾)的反向迭代器。

使用反向迭代器也可以进行排降序:

	int a[4] = { 4,27,22,20 };
	vector<int> v(a, a + 4);

	sort(v.rbegin(), v.rend());
	for (size_t i = 0; i < v.size(); ++i)
	{
		cout << v[i] << " ";
	}
	cout << endl;

在这里插入图片描述

Capacity(容量)

size

在这里插入图片描述

  • std::vector::size
  • size_type size() const;
  • 返回大小
	vector<int> v(10, 5);
	cout << v.size() << endl;

max_size

在这里插入图片描述

  • std::vector::max_size
  • size_type max_size() const;
  • 返回最大存储

【注意】不同的平台,最大的存储值不同

	vector<int> v(10, 5);
	cout << v.max_size() << endl;

resize

在这里插入图片描述

  • std::vector::resize
  • void resize (size_type n, value_type val = value_type());
  • 改变大小
	vector<int> v(10, 5);
	v.resize(20, 1);
	for (size_t i = 0; i < v.size(); ++i)
	{
		cout << v[i] << " ";
	}
	cout << endl;

capacity

在这里插入图片描述

  • std::vector::capacity
  • size_type capacity() const;
  • 返回分配存储容量的大小

下面是一段测试默认扩容机制

// 测试vector的默认扩容机制
void TestVectorExpand()
{
 	size_t sz;
 	vector<int> v;
 	sz = v.capacity();
	 cout << "making v grow:\n";
	 for (int i = 0; i < 100; ++i) 
 	 {
		 v.push_back(i);
 		 if (sz != v.capacity()) 
		 {
		 	sz = v.capacity();
 			cout << "capacity changed: " << sz << '\n';
 	     }
 	 }
}

使用这段代码分别在vs环境下和gcc环境下测试会发现,vs下capacity是以1.5倍增长的,而gcc环境下capacity是以2倍增长的。具体增长多少是根据具体的需求定义的。vs是PJ版本STL,g++是SGI版本STL。

empty

在这里插入图片描述

  • std::vector::empty
  • bool empty() const;
  • 测试容器是否为空
	vector<int> v1(10, 5);
	vector<int> v2;
	cout << v1.empty() << endl;
	cout << v2.empty() << endl;

reserve

在这里插入图片描述

  • std::vector::reserve
  • void reserve (size_type n);
  • 请求改变容量
	vector<int> v(10, 5);
	v.reserve(30);
	cout << v.capacity() << endl;

【注意】
1.使用reserve时是不允许使用下标[ ]的,这是因为下标[ ]在使用时需要调用size,而reserve不会改变size。
2.使用reserve需要添加数据时,可以使用push_back;使用resize添加数据时,可以使用下标+[ ]。这是因为reserve只能开辟空间,并不能改变size大小;而resize不仅可以开辟空间,同时也会改变size

Element access(元素访问)

operator[]

在这里插入图片描述

  • std::vector::operator[]
  • reference operator[] (size_type n);
  • const_reference operator[] (size_type n) const;
  • 访问元素
	vector<int> v(10, 5);
	for (size_t i = 0; i < v.size(); ++i)
	{
		v[i] = i;
	}

at

在这里插入图片描述

  • std::vector::at
  • reference at (size_type n);
  • const_reference at (size_type n) const;
  • 访问元素
	vector<int> v(10, 5);
	for (size_t i = 0; i < v.size(); ++i)
	{
		v.at(i) = i;
	}

【注意】使用下标+[ ]与at基本没有差别,唯一的差距是,使用下表+[] 报错时会断言,而使用at报错时会抛异常。

front

在这里插入图片描述

  • std::vector::front
  • reference front();
  • const_reference front() const;
  • 访问第一个元素
	int a[4] = { 4,27,22,20 };
	vector<int> v(a, a + 4);
	cout << v.front() << endl;

back

在这里插入图片描述

  • std::vector::back
  • reference back();
  • const_reference back() const;
  • 访问最后一个元素
	int a[4] = { 4,27,22,20 };
	vector<int> v(a, a + 4);
	cout << v.back() << endl;

Modifiers(修饰符)

assign

在这里插入图片描述

  • std::vector::assign
  • range (1)
    template < class InputIterator>
    void assign (InputIterator first, InputIterator last);
  • fill (2)
    void assign (size_type n, const value_type& val);
  • 分配元素内容
	vector<int> v(10, 5);
	v.assign(20, 1);

	for (size_t i = 0; i < v.size(); ++i)
	{
		cout << v[i] << " ";
	}
	cout << endl;

push_back

在这里插入图片描述

  • std::vector::push_back
  • void push_back (const value_type& val);
  • 在后面添加元素
	vector<int> v(10, 5);
	v.push_back(1);

	for (size_t i = 0; i < v.size(); ++i)
	{
		cout << v[i] << " ";
	}
	cout << endl;

pop_back

在这里插入图片描述

  • std::vector::pop_back
  • void pop_back();
  • 删除最后一个元素
	int a[4] = { 4,27,22,20 };
	vector<int> v(a, a + 4);
	v.pop_back();

	for (size_t i = 0; i < v.size(); ++i)
	{
		cout << v[i] << " ";
	}
	cout << endl;

insert

在这里插入图片描述

  • std::vector::insert
  • single element (1)
    iterator insert (iterator position, const value_type& val);
  • fill (2)
    void insert (iterator position, size_type n, const value_type& val);
  • range (3)
    template < class InputIterator >
    void insert (iterator position, InputIterator first, InputIterator last);
  • 插入元素
	int a[4] = { 4,27,22,20 };
	vector<int> v(a, a + 4);
	v.insert(v.begin() + 2, 15);

	for (size_t i = 0; i < v.size(); ++i)
	{
		cout << v[i] << " ";
	}
	cout << endl;

erase

在这里插入图片描述

  • std::vector::erase
  • iterator erase (iterator position);
  • iterator erase (iterator first, iterator last);
  • 删除元素
	int a[4] = { 4,27,22,20 };
	vector<int> v(a, a + 4);
	v.erase(v.begin() + 1);

	for (size_t i = 0; i < v.size(); ++i)
	{
		cout << v[i] << " ";
	}
	cout << endl;

swap

在这里插入图片描述

  • std::vector::swap
  • void swap (vector& x);
  • 交换内容
	int a[4] = { 4,27,22,20 };
	vector<int> v1(a, a + 4);
	vector<int> v2(10, 5);
	v1.swap(v2);

clear

在这里插入图片描述

  • std::vector::clear
  • void clear();
  • 清理内容
	vector<int> v2(10, 5);
	v2.clear();

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

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

相关文章

zephyr设置BLE广播数据实例

目录 实例1&#xff1a;静态开启广播数据实例2&#xff1a;动态更改广播数据实例3&#xff1a;创建可连接的广播 实例1&#xff1a;静态开启广播数据 新建一个hello world的工程模板。 在prj.conf中开启蓝牙 CONFIG_BTy这个宏&#xff0c;默认会开启广播支持 ( BT_BROADCAS…

1448.统计二叉树中的好节点数目

给你一棵根为 root 的二叉树&#xff0c;请你返回二叉树中好节点的数目。 「好节点」 X 定义为&#xff1a;从根到该节点 X 所经过的节点中&#xff0c;没有任何节点的值大于 X 的值。 示例 1&#xff1a; 输入&#xff1a;root [3,1,4,3,null,1,5] 输出&#xff1a;4 解释&am…

【算法】LRU缓存

难度&#xff1a;中等 题目&#xff1a; 请你设计并实现一个满足 LRU (最近最少使用) 缓存 约束的数据结构。 实现 LRUCache 类&#xff1a; LRUCache(int capacity) 以 正整数 作为容量 capacity 初始化 LRU 缓存int get(int key) 如果关键字 key 存在于缓存中&#xff0c;…

【人工智能新纪元】机器学习算法:探索智能背后的奥秘与常见利器

在这个日新月异的科技时代&#xff0c;人工智能&#xff08;AI&#xff09;如同一股不可阻挡的洪流&#xff0c;正深刻地改变着我们的世界。作为AI领域的核心驱动力之一&#xff0c;机器学习算法以其独特的魅力&#xff0c;引领着智能技术的飞速发展。今天&#xff0c;就让我们…

【学习】美国虚拟信用卡申请流程

WildCard 官方网址&#xff1a;https://bewildcard.com/i/PEACEFUL &#xff08;使用邀请码“PEACEFUL”可以享受开卡88 折优惠&#xff0c;注册时提示填写邀请码就可以填写&#xff09;

Vue3 组件向下通信 祖孙组件的通信 provide与inject

介绍 当父子间通信可以使用props&#xff0c;祖孙使用provide&#xff08;传递&#xff09;或inject&#xff08;接收&#xff09;&#xff0c; 这时不管组件套的多深都可以向下传递。 例子 现在有一个需求&#xff0c;把App.vue的数据传递到MusciPlay.vue里。 App.vue …

跟李沐学AI:模型选择、过拟合和欠拟合

目录 训练误差和泛化误差 验证数据集和测试数据集 K-则交叉验证 模型总结 过拟合和欠拟合 模型容量 模型容量的影响 估计模型容量 数据复杂度 拟合总结 训练误差和泛化误差 训练误差&#xff1a;模型在训练数据上的误差 泛化误差&#xff1a;模型在新数据上的误差 …

移掉 K 位数字

题目链接 移掉 K 位数字 题目描述 注意点 1 < k < num.length < 10^5num 仅由若干位数字&#xff08;0 - 9&#xff09;组成除了 0 本身之外&#xff0c;num 不含任何前导零 解答思路 关键是怎样移掉K位数字保证移除后的数字是最小的。观察规律可得&#xff0c;为…

基于LSTM及其变体的回归预测

1 所用模型 代码中用到了以下模型&#xff1a; 1. LSTM&#xff08;Long Short-Term Memory&#xff09;&#xff1a;长短时记忆网络&#xff0c;是一种特殊的RNN&#xff08;循环神经网络&#xff09;&#xff0c;能够解决传统RNN在处理长序列时出现的梯度消失或爆炸的问题。L…

GB35114国密算法-GMSSL

C有个三方库-GMSSL是可以进行GB35114所需要的SM2、SM3、SM4等加解密算法的&#xff0c;但是使用国密算法是需要申请报备的 GmSSL是由北京大学自主开发的国产商用密码开源库&#xff0c;实现了对国密算法、标准和安全通信协议的全面功能覆盖&#xff0c;支持包括移动端在内的主流…

SpringBoot整合Swagger报错:Failed to start bean ‘documentationPluginsBootstrapper

文章目录 1 问题背景2 问题原因3 修改SpringBoot配置文件 application.properties参考 1 问题背景 Swagger是SpringBoot中常用的API文档工具&#xff0c;在刚接触使用的时候&#xff0c;按照通用的代码进行配置&#xff0c;发现报错了 [main] ERROR org.springframework.boot…

【ARM AMBA AXI 入门 5.1 - QoS是什么?QoS是怎么工作的? 】

请阅读【ARM AMBA AXI 总线 文章专栏导读】 转自&#xff1a;揭秘数通知识&#xff1a;QoS是什么&#xff1f;QoS是怎么工作的&#xff1f;&#xff08;一&#xff09; 文章目录 QoS 概述综合服务和差分服务 QoS 工具报文分类报文标记流量监管和整形工具拥塞管理工具拥塞避免工…

JuiceFS缓存特性

缓存 对于一个由对象存储和数据库组合驱动的文件系统&#xff0c;缓存是本地客户端与远端服务之间高效交互的重要纽带。读写的数据可以提前或者异步载入缓存&#xff0c;再由客户端在后台与远端服务交互执行异步上传或预取数据。相比直接与远端服务交互&#xff0c;采用缓存技…

Linux 线程初步解析

1.线程概念 在一个程序里的一个执行路线就叫做线程&#xff08;thread&#xff09;。更准确的定义是&#xff1a;线程是“一个进程内部的控制序列。在linux中&#xff0c;由于线程和进程都具有id,都需要调度等等相似性&#xff0c;因此都可以用PCB来描述和控制,线程含有PCB&am…

[RuoYi-Vue] - 5. 部分代码分析

文章目录 &#x1f374;1. 后端部分代码分析1.1 BaseController1.2 TableDataInfo1.3 AjaxResult1.4 BaseEntity &#x1f378;2. 权限注解&#x1f37a;3. 前后端交互3.1 跨域问题 &#x1f374;1. 后端部分代码分析 1.1 BaseController 1.2 TableDataInfo 分页查询统一返回对…

如何用个人电脑搭建一台本地服务器,并部署云原生开发工具TitanIDE到服务器详细教程

服务器是一种高性能计算机&#xff0c;作为网络的节点&#xff0c;它存储、处理网络上80%的数据、信息&#xff0c;因此也被称为网络的灵魂。与普通计算机相比&#xff0c;服务器具有高速CPU运算能力、长时间可靠运行、强大I/O外部数据吞吐能力以及更好的扩展性。 服务器的主要…

Day07-ES集群加密,kibana的RBAC实战,zookeeper集群搭建,zookeeper基本管理及kafka单点部署实战

Day07-ES集群加密&#xff0c;kibana的RBAC实战&#xff0c;zookeeper集群搭建&#xff0c;zookeeper基本管理及kafka单点部署实战 0、昨日内容回顾:1、基于nginx的反向代理控制访问kibana2、配置ES集群TSL认证:3、配置kibana连接ES集群4、配置filebeat连接ES集群5、配置logsta…

自建Web网站部署——案例分析

作者主页: 知孤云出岫 目录 作者主页:如何自建一个Web网站一、引言二、需求分析三、技术选型四、开发步骤1. 项目初始化初始化前端初始化后端 2. 前端开发目录结构示例代码App.jsHome.js 3. 后端开发目录结构示例代码app.jsproductRoutes.jsProduct.js 4. 前后端连接安装axio…

ospf复习综合小实验

实验要求&#xff1a; 1&#xff0c;R4为ISP&#xff0c;其上只能配置IP地址&#xff1b;R4与其他所有直连设备间均使用公有IP 2&#xff0c;R3-R5/6/7为MGRE环境&#xff0c;R3为中心站点&#xff1b; 3&#xff0c;整个OSPF环境IP基于172.16.0.0/16划分&#xff1b; 4&#…

redis其他类型和配置文件

很多博客只讲了五大基本类型&#xff0c;确实&#xff0c;是最常用的&#xff0c;而且百分之九十的程序员对于Redis只限于了解String这种最常用的。但是我个人认为&#xff0c;既然Redis官方提供了其他的数据类型&#xff0c;肯定是有相应的考量的&#xff0c;在某些特殊的业务…