C++ vector基本操作

目录

一、介绍

二、定义

三、迭代器

四、容量操作

1、size

2、capacity

3、empty

4、resize

5、reserve

总结(扩容机制)

五、增删查改

1、push_back & pop_back

2、find

3、insert

4、erase

5、swap

6、operator[]


一、介绍

vector的文档介绍

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

vector的使用

vector学习时一定要学会查看文档:vector的文档介绍,vector在实际中非常的重要,在实际中我们熟悉常见的接口就可以。

二、定义

这些是C++标准库中`vector`类的构造函数的不同重载形式。下面是对每个构造函数的解释:

1. 无参构造函数:`vector()` 

vector<int> v;
  • 创建一个空的`vector`对象,不包含任何元素。

2. 构造并初始化n个val:`vector(size_type n, const value_type& val = value_type())`

vector<int> v1(10, 1);
  • 创建一个包含`n`个元素的`vector`对象,每个元素都初始化为`val`。
  • 可以选择提供一个初始值`val`,如果未提供,则使用默认值类型的默认构造函数进行初始化。

3. 使用迭代器进行初始化构造 :`vector(InputIterator first, InputIterator last)`

string s1("hello");
vector<char> v3(s1.begin(), s1.end());
  • 创建一个`vector`对象,并使用范围 `[first, last)` 内的元素进行初始化。
  • `first` 和 `last` 是迭代器,指定了要复制的元素范围。
  • 这个构造函数允许使用迭代器来指定要复制的元素范围,可以是数组、容器或其他可迭代对象。

4. 拷贝构造函数:`vector(const vector& x)` 重点

vector<int>v1(v);
  • 创建一个新的`vector`对象,其元素与另一个`vector`对象`x`相同。
  • 拷贝构造函数用于创建一个副本,新的`vector`对象将独立于原始对象,对其中一个对象的修改不会影响另一个对象。

举例演示一下,其中输出和string类一样,有三种方式:范围for [ ] 迭代器。

void test1()
{//无参构造vector<int> v;v.push_back(1);v.push_back(2);v.push_back(3);//三种输出方式 范围for [] 迭代器for (auto a : v){cout << a << " ";}cout << endl;for (size_t i = 0; i < v.size(); i++){cout << v[i] << " ";}cout << endl;//vector<int>::iterator it = v.begin();auto it = v.begin();while (it != v.end()){cout << *it << " ";++it;}cout << endl;//拷贝构造vector<int> copy(v);for (auto a : copy) {cout << a << " ";}cout << endl;
}
void test2()
{//构造并初始化vector<int> v1(6, 6);for (auto a : v1){cout << a << " ";}cout << endl;//迭代器vector<int> v2(v1.begin(), v1.end());for (auto b : v2){cout << b << " ";}cout << endl;string s1("hello");vector<char> v3(s1.begin(), s1.end());for (auto b : v3){cout << b << " ";}}
int main()
{test1();cout << endl;test2();return 0;
}

三、迭代器

begin()/end()获取第一个数据位置的iterator / const_iterator, 获取最后一个数据的下一个位置的iterator / const_iterator

rbegin()/rend()获取最后一个数据位置的reverse_iterator,获取第一个数据前一个位置的reverse_iterator

通过使用这些接口,可以在vector中进行迭代操作。

  • 例如,使用begin()end()可以遍历vector中的元素,而使用rbegin()rend()可以反向遍历vector中的元素。
  • 请注意,对于只读的vector,应使用const_iteratorconst_reverse_iterator来确保不修改vector的元素。
void test3()
{vector<int> v;v.push_back(1);v.push_back(2);v.push_back(3);//正向迭代器vector<int>::iterator it = v.begin();while (it != v.end()){cout << *it << " ";++it;}cout << endl;//反向迭代器vector<int>::reverse_iterator rit = v.rbegin();while (rit != v.rend()){cout << *rit << " ";++rit;}
}
int main()
{test3();return 0;
}

四、容量操作

1、size

获取数据个数。
int main() {std::vector<int> v = {1, 2, 3, 4, 5};std::cout << "Size of vector: " << v.size() << std::endl;return 0;
}

2、capacity

capacity获取容量大小。
int main() {std::vector<int> v;std::cout << "Initial capacity: " << v.capacity() << std::endl;for (int i = 0; i < 10; i++) {v.push_back(i);std::cout << "Capacity after pushing " << i << ": " << v.capacity() << std::endl;}return 0;
}

3、empty

判断是否为空。
int main() {std::vector<int> v;std::cout << "Is vector empty? " << (v.empty() ? "Yes" : "No") << std::endl;v.push_back(1);std::cout << "Is vector empty? " << (v.empty() ? "Yes" : "No") << std::endl;return 0;
}

4、resize

改变vector的size。
void resize (size_type n, value_type val = value_type());
  1. 调整容器的大小,使其包含 n 个元素。
  2. 如果 n 小于当前容器大小,则内容将减少到其前 n 个元素,删除超出的元素(并销毁它们)。
  3. 如果 n 大于当前容器大小,则通过在末尾插入任意数量的元素来扩展内容,以达到 n 的大小。如果指定了 val,则新元素将初始化为 val 的副本,否则,它们将初始化值。
  4. 如果 n 也大于当前容器容量,则会自动重新分配分配的存储空间。
  5. 请注意,此函数通过插入或擦除容器中的元素来更改容器的实际内容。
int main() {std::vector<int> v = {1, 2, 3, 4, 5};v.resize(7, 100);for (int i : v) {std::cout << i << " ";}std::cout << std::endl;v.resize(3);for (int i : v) {std::cout << i << " ";}return 0;
}

5、reserve

改变vector的capacity。
reserve(): 这个方法更改vector的capacity。如果新的capacity大于当前的capacity,那么vector的内存将被重新分配以适应更多的元素。如果新的capacity小于当前的capacity,那么这个方法不会有任何效果。
int main() {std::vector<int> v;std::cout << "Initial capacity: " << v.capacity() << std::endl;v.reserve(10);std::cout << "Capacity after reserving: " << v.capacity() << std::endl;return 0;
}

总结(扩容机制)

  • capacity的代码在vs和g++下分别运行会发现,vs下capacity是按1.5倍增长的,g++是按2倍增长的
  • 这个问题经常会考察,不要固化的认为,vector增容都是2倍,具体增长多少是根据具体的需求定义的。vs是PJ版本STL,g++是SGI版本STL。
  • reserve只负责开辟空间,如果确定知道需要用多少空间,reserve可以缓解vector增容的代价缺陷问题。
  • resize在开空间的同时还会进行初始化,影响size。

通过下面代码可以观察到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';}}
}

如果已经确定vector中要存储元素大概个数,可以提前将空间设置足够就可以避免边插入边扩容导致效率低下的问题了。

void TestVectorExpandOP()
{vector<int> v;size_t sz = v.capacity();v.reserve(100); // 提前将容量设置好,可以避免一遍插入一遍扩容cout << "making bar 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';}}
}

五、增删查改

1、push_back & pop_back

尾插&尾删
int main() {std::vector<int> v;v.push_back(1);v.push_back(2);v.push_back(3);for (int i : v) {std::cout << i << " ";}cout << endl;v.pop_back();for (int i : v) {std::cout << i << " ";}return 0;
}

2、find

  • 查找 find函数是一个算法模块中的函数,用于在vector中查找特定的元素。
  • 它需要提供要查找的元素的起始和结束位置,并返回一个指向该元素的迭代器。
  • 例如,如果有一个vector v,可以使用std::find(v.begin(), v.end(), 5)在v中查找整数5。

3、insert

  • 插入 insert函数用于在指定位置之前插入一个元素。它需要提供要插入的位置和要插入的值作为参数。
  • 例如,如果有一个vector v,可以使用v.insert(v.begin() + 2, 10)在v的第三个位置插入整数10。

4、erase

  • 删除 erase函数用于删除指定位置的元素。它需要提供要删除的位置作为参数,并返回一个指向被删除元素之后位置的迭代器。
  • 例如,如果有一个vector v,可以使用v.erase(v.begin() + 3)删除v的第四个元素。

下面这段代码演示了对vector进行插入、查找和删除操作的示例。

void test5()
{vector<int> v;v.push_back(1); // 在vector末尾插入元素1v.push_back(2); // 在vector末尾插入元素2v.push_back(3); // 在vector末尾插入元素3v.push_back(4); // 在vector末尾插入元素4for (auto e : v){cout << e << " "; // 输出vector中的每个元素}cout << endl;// 在vector中查找值为2的元素vector<int>::iterator pos = find(v.begin(), v.end(), 2); if (pos != v.end()){v.insert(pos, 20); // 在找到的位置之前插入元素20}for (auto e : v){cout << e << " "; // 输出修改后的vector中的每个元素}cout << endl;pos = find(v.begin(), v.end(), 2); // 再次查找值为2的元素if (pos != v.end()){v.erase(pos); // 删除找到的元素}for (auto e : v){cout << e << " "; // 输出修改后的vector中的每个元素}cout << endl;v.erase(v.begin()); // 删除vector的第一个元素for (auto e : v){cout << e << " "; // 输出修改后的vector中的每个元素}cout << endl;
}int main()
{test5();return 0;
}

5、swap

  • 交换 swap函数用于交换两个vector的数据空间。它需要提供另一个vector作为参数,并将当前vector的内容与参数vector的内容进行交换。
  • 例如,如果有两个vector v1和v2,可以使用v1.swap(v2)交换它们的内容。
int main() {std::vector<int> v1 = { 1, 2, 3 };std::vector<int> v2 = { 4, 5, 6 };v1.swap(v2);for (int i : v1) {cout << i << " ";}cout << endl;for (int i : v2) {cout << i << " ";}return 0;
}

6、operator[]

像数组一样访问

int main()
{vector<int> v;v.push_back(1);v.push_back(2);v.push_back(3);v.push_back(4);for (size_t i = 0; i < v.size(); ++i){cout << v[i] << " ";}return 0;
}

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

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

相关文章

前端CSS(层叠样式表)总结

CSS2总结 一、CSS基础 1. CSS简介 CSS 的全称为&#xff1a;层叠样式表 ( Cascading Style Sheets ) 。CSS 也是一种标记语言&#xff0c;用于给 HTML 结构设置样式&#xff0c;例如&#xff1a;文字大小、颜色、元素宽高等等。 简单理解&#xff1a; CSS 可以美化…

<软考>软件设计师-3程序设计语言基础(总结)

(一) 程序设计语言概述 1 程序设计语言的基本概念 1-1 程序设计语言的目的 程序设计语言是为了书写计算机程序而人为设计的符号语言&#xff0c;用于对计算过程进行描述、组织和推导。 1-2 程序语言分类 低级语言 : 机器语言&#xff08;计算机硬件只能识别0和1的指令序列)&…

java设计模式学习之【装饰器模式】

文章目录 引言装饰器模式简介定义与用途实现方式 使用场景优势与劣势装饰器模式在Spring中的应用画图示例代码地址 引言 在日常生活中&#xff0c;我们常常对基本事物添加额外的装饰以增强其功能或美观。例如&#xff0c;给手机加一个保护壳来提升其防护能力&#xff0c;或者在…

SwiftUI 中创建一个自定义文件管理器只需4步!你敢信!?

概览 在 SwiftUI 中写一个自定义文件内容的管理器有多难呢&#xff1f; 答案可能超乎小伙伴们的想象&#xff1a;仅需4步&#xff01;可谓是超级简单&#xff01; 在本篇博文中&#xff0c;您将学到如下内容&#xff1a; 概览1. 第一步&#xff1a;定义文件类型2. 第二步&…

Dockerfile 指令的最佳实践

这些建议旨在帮助您创建一个高效且可维护的Dockerfile。 一、FROM 尽可能使用当前的官方镜像作为镜像的基础。Docker推荐Alpine镜像&#xff0c;因为它受到严格控制&#xff0c;体积小&#xff08;目前不到6 MB&#xff09;&#xff0c;同时仍然是一个完整的Linux发行版。 FR…

从主从复制到哨兵模式(含Redis.config配置模板)

文章目录 前言一、主从复制1.概述2.作用3.模拟实践搭建场景模拟实践 二、哨兵模式1.概述2.配置使用3.优缺点4.sentinel.conf完整配置 总结 前言 从主从复制到哨兵模式。 一、主从复制 1.概述 主从复制&#xff0c;是指将一台 Redis 服务器的数据&#xff0c;复制到其他的 Red…

0010Java安卓程序设计-ssm基于安卓的掌上校园系统

文章目录 **摘要**目录系统实现5.2管理员功能模块开发环境 编程技术交流、源码分享、模板分享、网课分享 企鹅&#x1f427;裙&#xff1a;776871563 摘要 随着Internet的发展&#xff0c;人们的日常生活已经离不开网络。未来人们的生活与工作将变得越来越数字化&#xff0c;…

Livox_ros_driver2 消息 (msg) 类型对 SLAM 应用程序的适配

Title: Livox_ros_driver2 消息 (msg) 类型对 SLAM 应用程序的适配 文章目录 I 前言II. 查看 ROS 消息III. Livox ROS 驱动的消息类型IV. 适配修改应用程序V. 总结 I 前言 有时候, 拿到最新的 Livox 激光传感器, 比如 HAP, 原厂也提供了 ROS 驱动支持 livox_ros_drivers2 (htt…

UE蓝图 里的函数,编辑模式在Sequence里执行

在蓝图里创建CustomFunction &#xff0c;把蓝图拖入Sequence &#xff0c;添加事件 即可调用 如果需要在Sequence里K 蓝图里的变量&#xff0c;需要勾上向过场动画公开

JS中Map对象与object的区别

若想了解Map对象可以阅读本人这篇ES6初步了解Map Map对象与object有什么区别&#xff1f;让我为大家介绍一下吧&#xff01; 共同点 二者都是以key-value的形式对数据进行存储 const obj {name:"zs",age:18}console.log(obj)let m new Map()m.set("name&quo…

《深入理解计算机系统》学习笔记 - 第三课 - 浮点数

Floating Point 浮点数 文章目录 Floating Point 浮点数分数二进制示例能代表的数浮点数的表示方式浮点数编码规格化值规格化值编码示例 非规格化的值特殊值 示例IEEE 编码的一些特殊属性四舍五入&#xff0c;相加&#xff0c;相乘四舍五入四舍五入的模式二进制数的四舍五入 浮…

带负离子的高速吹风筒方案介绍---【其利天下技术】

负离子吹风筒的产品概念&#xff0c;在吹风筒的产品系列里早就存在的。近年来&#xff0c;随着高速风筒的逐渐普及&#xff0c;产品商都开始把这些产品概念带了进来。一方面提升产品的核心竞争力&#xff0c;另一方面也是为了提升产品体验度&#xff0c;给用户带来不一样的产品…

夯实c基础

夯实c基础 区别&#xff1a; 图一的交换&#xff0c;&#xff08;交换的是地址而不是两数&#xff09;无法实现两数的交换。 题干以下程序的输出结果为&#xff08; c  &#xff09;。 void fun(int a, int b, int c){ ca*b; } void main( ){ int…

ssh安装和Gitee(码云)源码拉取

文章目录 安装ssh服务注册码云公钥设置码云账户SSH公钥安装git客户端和git-lfs源码获取 安装ssh服务 更新软件源&#xff1a; sudo apt-get update安装ssh服务 sudo apt-get install openssh-server检查ssh是否安装成功 which ssh输出&#xff1a; /usr/bin/ssh启动ssh 服…

虾皮定价公式:如何在Shopee上为您的商品设置合适的价格?

在Shopee这样的电商平台上销售商品&#xff0c;定价是一个至关重要的因素。一个合理的定价策略不仅可以吸引更多的买家&#xff0c;还可以确保您从每个商品中获得足够的利润。虾皮&#xff08;Shopee&#xff09;为卖家提供了一个简化的定价公式&#xff0c;考虑了多个因素&…

浅析AI智能视频监控技术在城市交通中的作用及意义

城市交通作为整个城市的整体脉络&#xff0c;每天都发挥着重要作用&#xff0c;为了最大程度地避免城市交通堵塞、提高城市交通效率&#xff0c;智能视频监控系统发挥了重要作用。具体表现在以下几个方面&#xff1a; 1、交通违规监管&#xff1a;TSINGSEE青犀智能视频监控系统…

【JavaScript】JS——Map数据类型

【JavaScript】JS——Map数据类型 什么是Map?特性Map与Object的比较 map的创建map的属性map相关方法map的遍历 什么是Map? 存储键值对的对象。 能够记住键的原始插入顺序任何值&#xff08;对象或原始值&#xff09;都可以作为键或值。 特性 Map中的一个键只能出现一次&am…

【三维重建】多频外差相位展开(C++实现)

在结构光三维重建中&#xff0c;通过相移法求解出来的相位是包裹相位&#xff08;在 [&#xff0d;π/2,π/2] 间成周期性 &#xff09; 我们想要用相位找到相机与投影仪间的对应像素&#xff0c;就需要进行相位展开&#xff0c;确保每一行的相位值是唯一的。 多频外差是相位…

JVM虚拟机(已整理,已废弃)

# JVM组成 ## 简述程序计数器 线程私有&#xff0c;内部保存class字节码的行号。用于记录正在执行的字节码指令的地址。 线程私有-每个线程都有自己的程序计数器PC&#xff0c;用于记录当前线程执行哪个行号 ## 简述堆 ## 简述虚拟机栈 ## 简述堆栈区别 ## 方法内局部变量是…

SRC挖掘漏洞XSS

Markdown是一种轻量级标记语言&#xff0c;创始人为约翰格鲁伯&#xff08;John Gruber&#xff09;。它允许人们使用易读易写的纯文本格式编写文档&#xff0c;然后转换成有效的 XHTML&#xff08;或者HTML&#xff09;文档。这种语言吸收了很多在电子邮件中已有的纯文本标记的…