【STL】:vector用法详解

朋友们、伙计们,我们又见面了,本期来给大家解读一下有关vector的基础用法,如果看完之后对你有一定的启发,那么请留下你的三连,祝大家心想事成!

C 语 言 专 栏:C语言:从入门到精通

数据结构专栏:数据结构

个  人  主  页 :stackY、

C + + 专 栏   :C++

Linux 专 栏  :Linux

​ 

目录

1. vector介绍

2. vector使用

2.1vector的定义

2.2vector迭代器

2.3vector空间增长

2.4vector增删查改

2.4.1 迭代器失效


1. vector介绍

vector官方文档参考

类似于数据结构中讲到过的顺序表

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

2. vector使用

vector学习时一定要学会查看文档:vector官方文档参考,vector在实际中非常的重要,在实际中我们熟悉常见的接口就可以,下面列出了哪些接口是要重点掌握的。

2.1vector的定义

构造函数声明接口说明
vector()无参构造
vector(size_type n, const value_type& val = value_type())构造并初始化n个val
vector (const vector& x)拷贝构造
vector (InputIterator first, InputIterator last)使用迭代器进行初始化构造

 在使用vector之前需要包含vector对应的头文件:#include <vector>

#include <vector>//定义测试
void test_vector1()
{//1. 无参vector<int> v1;//2. n个val构造vector<int> v2(10, 0);//3. 使用迭代器区间vector<int> v3(v2.begin(), v2.end());//4. 使用其他容器的迭代器区间string str = "Hello World!";vector<int> v4(str.begin(), str.end());//拷贝构造vector<int> v5(v2);
}

2.2vector迭代器

iterator的使用接口说明
begin +
end
获取第一个数据位置的iterator/const_iterator, 获取最后一个数据的下一个位置
的iterator/const_iterator
rbegin + rend获取最后一个数据位置的reverse_iterator,获取第一个数据前一个位置的
reverse_iterator

//迭代器
void test_vector2()
{vector<int> v2(10, 0);for (size_t i = 0; i < v2.size(); i++){//vector也可以使用[]cout << v2[i] << " ";}cout << endl;//迭代器的使用//vector<int>::iterator it = v2.begin();auto it = v2.begin();while (it != v2.end()){cout << *it << " ";it++;}cout << endl;//范围forfor (auto e : v2){cout << e << " ";}cout << endl;
}

2.3vector空间增长

容量空间接口说明
size获取数据个数
capacity获取容量大小
empty判断是否为空
resize改变vector的size
reserve 改变vector的capacity
  • 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';}}
}

 vs:运行结果:vs下使用的STL基本是按照1.5倍方式扩容
making foo grow:
capacity changed: 1
capacity changed: 2
capacity changed: 3
capacity changed: 4
capacity changed: 6
capacity changed: 9
capacity changed: 13
capacity changed: 19
capacity changed: 28
capacity changed: 42
capacity changed: 63
capacity changed: 94

capacity changed: 141


g++运行结果:linux下使用的STL基本是按照2倍方式扩容
making foo grow:
capacity changed: 1
capacity changed: 2
capacity changed: 4
capacity changed: 8
capacity changed: 16
capacity changed: 32
capacity changed: 64
capacity changed: 128

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

重点来看一下resize和reserve:

如我我们要对一个vector进行初始化,那必然先要进行空间的创建,然后再进行初始化,那么在这里是需要resize还是reserve?

resize改变的是vector的size,而size代表的是有效元素的个数,reserve改变的vector的capacity,而capacity代表的是有效空间,所以要对一个vector进行初始化是需要使用resize的。

//容量
void test_vector3()
{vector<int> v;//v.reserve(100); // size == 0    capacity == 100v.resize(100); //  size == 100   capacity == 100//初始化for (size_t i = 0; i < v.size(); i++){v[i] = i;}for (auto e : v){cout << e << " ";}cout << endl;
}

2.4vector增删查改

vector增删查改接口说明
push_back尾插
pop_back 尾删
find查找。(注意这个是算法模块实现,不是vector的成员接口)
insert在position之前插入val
erase删除position位置的数据
swap交换两个vector的数据空间
operator[ ] 像数组一样访问

1. 尾插、尾删 

void test_vector4()
{vector<int> v;//尾插v.push_back(1);v.push_back(2);v.push_back(3);v.push_back(4);v.push_back(5);for (auto e : v){cout << e << " ";}cout << endl;//尾删v.pop_back();v.pop_back();for (auto e : v){cout << e << " ";}cout << endl;
}

2. 插入(insert)、删除(erase)、查找(find)

find算法不属于vector中的接口(方便插入和删除)

//插入、删除
void test_vector5()
{vector<int> v;v.push_back(1);v.push_back(2);v.push_back(3);v.push_back(4);v.push_back(5);//头插v.insert(v.begin(), 0);//头删v.erase(v.begin());//在pos位置插入v.insert(v.begin() + 2, 30);//删除pos位置v.erase(v.begin() + 2);//在pos位置插入n个valv.insert(v.begin() + 1, 5, 10);//找到5个10并删除for (size_t i = 0; i < 5; i++){v.erase(find(v.begin(), v.end(), 10));}
}

 

2.4.1 迭代器失效

当使用vector进行insert、erase操作时,vector的迭代器都会失效:

void test_vector7()
{vector<int> v;v.push_back(1);v.push_back(2);v.push_back(3);v.push_back(4);v.push_back(5);vector<int>::iterator it = v.begin();while (it != v.end()){cout << *it << ' ';v.insert(v.begin() + 2, 7);  //造成迭代器失效it++;}
}void test_vector8()
{vector<int> v = { 1,2,3,4,5,6,7,8,9,10 };vector<int>::iterator it = v.begin();//删除偶数while (it != v.end()){if (*it % 2 == 0){v.erase(it);}it++;}
}

同样的string的insert和erase也会导致迭代器失效:

void TestString()
{string s("hello");auto it = s.begin();// 放开之后代码会崩溃,因为resize到20会string会进行扩容// 扩容之后,it指向之前旧空间已经被释放了,该迭代器就失效了// 后序打印时,再访问it指向的空间程序就会崩溃//s.resize(20, '!');while (it != s.end()){cout << *it;++it;}cout << endl;it = s.begin();while (it != s.end()){it = s.erase(it);// 按照下面方式写,运行时程序会崩溃,因为erase(it)之后// it位置的迭代器就失效了// s.erase(it);++it;}
}

迭代器失效解决办法:在使用前,对迭代器重新赋值即可。 

3. 清理(clear)和缩容 (shrink_to_fit)

clear:只清理数据,不释放空间。

shrink_to_fit:将capacity缩到size

void test_vector6()
{vector<int> v;v.push_back(1);v.push_back(2);v.push_back(3);v.push_back(4);v.push_back(5);for (auto e : v){cout << e << " ";}cout << endl;cout << v.size() << endl;cout << v.capacity() << endl;//清理v.clear();cout << v.size() << endl;cout << v.capacity() << endl;//缩容v.shrink_to_fit(); cout << v.size() << endl;cout << v.capacity() << endl;
}

朋友们、伙计们,美好的时光总是短暂的,我们本期的的分享就到此结束,欲知后事如何,请听下回分解~,最后看完别忘了留下你们弥足珍贵的三连喔,感谢大家的支持!

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

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

相关文章

k8s-----24、亲和力Affinity

1、应用场景 pod和节点间的关系&#xff1a; 某些Pod优先选择有ssdtrue标签的节点&#xff0c;如果没有在考虑部署到其它节点;某些Pod需要部署在ssdtrue和typephysical的节点上&#xff0c;但是优先部署在ssdtrue的节点上; pod和pod间的关系&#xff1a; 同一个应用的Pod不…

Wt库的C++下载器程序

以下是一个使用Wt库的C下载器程序&#xff0c;用于下载音频文件。此程序使用了的代码。 #include <Wt/Wt.h> #include <Wt/Http/DiskCache.h> #include <Wt/Http/HttpClient.h> ​ // 定义一个函数来获取服务器 static std::string get_proxy() {// 使用Wt:…

idea免费插件分享

分享一些在开发中常用到的idea插件&#xff0c;都是一些我自己常用的&#xff0c;希望对各位程序员有帮助吧。 1、Chinese Language 汉化插件&#xff1a;中文语言包将为您的 IntelliJ IDEA, AppCode, CLion, DataGrip, GoLand, PyCharm, PhpStorm, RubyMine, WebStorm, 和Rid…

SQL基础练习题1

文章目录 主要内容一.SQL基础练习题1.下面的 SELECT 语句是否执行成功&#xff1a;代码如下&#xff08;示例&#xff09;: 2.在下面的语句中有 4 个编码错误&#xff0c;请找出它们&#xff1a;代码如下&#xff08;示例&#xff09;: 3.显示 DEPARTMENTS 表的结构。代码如下&…

js创建 ajax 过程

目录 前言&#xff1a;AJAX 技术的重要性 详解&#xff1a;创建 AJAX 请求的步骤 1. 创建 XMLHttpRequest 对象 2. 配置请求 3. 处理响应 4. 发送请求 5. 处理异步请求 解析&#xff1a;AJAX 请求的重要性和限制 总结&#xff1a; 前言&#xff1a;AJAX 技术的重要性 …

漏洞复现--用友 畅捷通T+ .net反序列化RCE

免责声明&#xff1a; 文章中涉及的漏洞均已修复&#xff0c;敏感信息均已做打码处理&#xff0c;文章仅做经验分享用途&#xff0c;切勿当真&#xff0c;未授权的攻击属于非法行为&#xff01;文章中敏感信息均已做多层打马处理。传播、利用本文章所提供的信息而造成的任何直…

javaEE -8(9000字详解网络编程)

一&#xff1a;网络编程基础 1.1 网络资源 所谓的网络资源&#xff0c;其实就是在网络中可以获取的各种数据资源&#xff0c;而所有的网络资源&#xff0c;都是通过网络编程来进行数据传输的。 用户在浏览器中&#xff0c;打开在线视频网站&#xff0c;如优酷看视频&#xff…

【jvm】虚拟机栈之操作数栈

目录 一、说明二、图解2.1 代码示例2.2 javap操作 三、图示3.1 bipush 153.2 istore_13.3 bipush 83.4 istore_23.5 iload_13.6 iload_23.7 iadd3.8 istore_33.9 return结束 四、附加 一、说明 1.Operand Stack 2.栈可以使用数组或链表来实现 3.每一个独立的栈帧包含一个后进先…

arcgis js api 4.x通过TileLayer类加载arcgis server10.2发布的切片服务跨域问题的解决办法

1.错误复现 2.解决办法 2.1去https://github.com/Esri/resource-proxy 网站下载代理配置文件&#xff0c;我下载的是最新的1.1.2版本&#xff0c;这里根据后台服务器配置情况不同有三种配置文件&#xff0c;此次我用到的是DotNet和Java. 2.2 DotNet配置 2.2.1 对proxy文件增加…

SpringCloud复习:(6)feign整合hystrix

一、添加依赖 <dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-netflix-hystrix</artifactId><version>2.2.5.RELEASE</version></dependency>二、配置文件开启feign对hystrix的支…

相交链表-力扣

一、题目描述 题目链接&#xff1a;力扣&#xff08;LeetCode&#xff09;官网 - 全球极客挚爱的技术成长平台 二、题解 注意题目所说的相交&#xff0c;相交节点不只是数值上的相等&#xff0c;而是相交以后两条链变成一条链。 解决改题目&#xff0c;我们可以&#xff1a;…

LeetCode75——Day16

文章目录 一、题目二、题解 一、题目 1004. Max Consecutive Ones III Given a binary array nums and an integer k, return the maximum number of consecutive 1’s in the array if you can flip at most k 0’s. Example 1: Input: nums [1,1,1,0,0,0,1,1,1,1,0], k …

【洛谷 P1518】[USACO2.4] 两只塔姆沃斯牛 The Tamworth Two 题解(深度优先搜索)

[USACO2.4] 两只塔姆沃斯牛 The Tamworth Two 题目描述 两只牛逃跑到了森林里。Farmer John 开始用他的专家技术追捕这两头牛。你的任务是模拟他们的行为&#xff08;牛和 John&#xff09;。 追击在 10 10 10 \times 10 1010 的平面网格内进行。一个格子可以是&#xff1…

面试中经常问道的问题一

ActiveMQ持久订阅设置 在JMS中,Topic实现publish和subscribe语义。一条消息被publish时,它将发到所有感兴趣的订阅者,所以零到多个subscriber将接收到消息的一个拷贝。但是在消息代理接收到消息时,只有激活订阅的subscriber能够获得消息的一个拷贝。 JMS Queue执行load bal…

C使用const详细(学习笔记)

1、对形参使用const&#xff0c;告诉编译器&#xff0c;该函数不能修改arr指向的数组中的内容。 int sum(const int * arr,int n);2、指向const的指针不能用于改变值 3、把const数据或非const数据的地址初始化为只想const的指针或为其赋值时合法的 //带const的指针&#xff0…

景联文科技提供4D-BEV标注工具:提升自动驾驶感知能力的精准数据支持

4D-BEV标注是一种用于自动驾驶领域的数据标注方法。在3D空间的基础上&#xff0c;加入了时间维度&#xff0c;形成了四个维度。这种方法通过精准地跟踪和记录动态对象&#xff08;如车辆、行人&#xff09;的运动轨迹、姿势变化以及速度等信息&#xff0c;全面理解和分析动态对…

【Python机器学习】零基础掌握DictVectorizer特征提取

如何有效地处理和转换非数值型的数据,以便能够用于机器学习模型? 在实际生活中,特别是在数据分析和机器学习领域,经常会遇到需要处理的数据并不都是数值型的。比如在电商网站的用户行为分析中,可能会记录用户的性别、购买产品类型、支付方式等信息。这些数据中有些是分类…

avaScript 条件分支语句以及示例和详细代码解释为什么这样写呢(1)

在JavaScript中&#xff0c;条件分支语句主要有if语句、else if语句和else语句。条件分支语句用于根据不同的条件执行不同的代码块。下面是一个使用条件分支语句的示例代码&#xff1a; javascript let num 10;if (num > 0) {console.log("num是一个正数"); } e…

Java中JVM、JRE和JDK三者有什么区别和联系?

任何语言或者软件的运行都需要环境。就像人要生活在空气中&#xff0c;鱼要活在水中&#xff0c;喜阴植物就不能放在阳光下暴晒一样&#xff0c;任何对象个体的存在都离不开其所需要的环境&#xff0c;编程语言亦是一样的。 java 语言的开发运行&#xff0c;也离不开 Java 语言…

vue中前端导出excel的两种方法

vue中前端导出excel方法 其实前端导出和后端导出的处理方式很类似 我们这样主要是根据后端接口返回的不分页的列表来进行整体导出功能的实现 依赖文件 可以直接cv到项目中 utils下的 Export2Excel.js文件 require(script-loader!file-saver); require(script-loader!xlsx/d…