C++_Vector的学习

1.概述

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

2.成员函数

2.1构造函数

vector()无参构造
vectorsize_type n, const value_type& val = value_type()构造并初始化nval
vector (const vector& x)拷贝构造
vector (InputIterator first, InputIterator last)使用迭代器进行初始化构造

2.2iterator 的使用

endrend返回的迭代器是指向最后一个元素后面的位置)

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

2.3空间增长

size
获取数据个数
capacity
获取容量大小
empty
判断是否为空
resize
改变 vector size
reserve
改变 vector capacity

resizereserve的对比
reserve是容器预留空间,但在空间内不真正创建元素对象,没有添加新的对象之前,不能访问容器内的元素,reserve()函数和容器的capacity息息相关:
        如果n>容器的当前capacity,该函数会使得容器重新分配内存使capacity达到n
        如果n<=capacity,该函数调用不会导致内存重新分配,并且容器的capacity不会改变
        reserve()避免多次不必要的扩容,不会影响size,不会改变任何元素
        vs下capacity是按1.5倍增长的,g++是按2倍增长的

resize是改变容器的size大小,且创建对象,可以访问容器内的对象
         如果n<当前容器的size,则将元素减少到前n个,移除多余的元素(并销毁)
         如果n>当前容器的size,则在容器中追加元素,如果val指定了,则追加的元素为val的拷贝,否则,默认初始化
         如果n>当前容器capacity容量,内存会自动重新分配

2.4增删查改

push_back尾插
pop_back 尾删
find查找,注意这个是算法模块实现,不是vector的成员接口
insertposition插入val
erase删除position位置的数据
swap交换两个vector的数据空间
operator[] 像数组一样访问
vector 迭代器失效问题:
迭代器的主要作用就是让算法能够不用关心底层数据结构,其底层实际就是一个指针,或者是对指针进行了 封装 ,比如: vector 的迭代器就是原生态指针 T* 。因此 迭代器失效,实际就是迭代器底层对应指针所指向的 空间被销毁了,而使用一块已经被释放的空间 ,造成的后果是程序崩溃 ( 如果继续使用已经失效的迭代器, 程序可能会崩溃 )
容器类插入删除
list所有迭代器不失效有且仅有被删除的节点的迭代器才失效
vector当 vector 的容量(capacity)不改变时, 只失效之后的迭代器, 否则全部失效被删除节点之后的迭代器全部失效
set,map所有迭代器不失效有且仅有被删除的节点的迭代器才失效

insert导致的失效:
会引起其底层空间改变的操作都有可能是迭代器失效,比如:resizereserveinsert、assign、push_back等操作,都有可能会导致vector扩容,也就是说vector底层原理旧空间被释放掉,而在打印时,it还使用的是释放之间的旧空间,在对it迭代器操作时,实际操作的是一块已经被释放的空间,而引起代码运行时崩溃

	iterator insert(iterator pos, const T& x) {assert(pos >= _start);assert(pos <= _finish);if(_finish == _endOfStorage) {size_t len = pos - _start;reserve(capacity() == 0 ? 4 : capacity() * 2);//发生扩容,pos的位置不再正确,需要更新pos = _start + len;}iterator it = _finish - 1;while (it >= pos) {*(it + 1) = *it;it--;}*pos = x;_finish++;return _start;}void test_vector7() {//迭代器失效1:inset插入vector<int> v1;v1.push_back(1);v1.push_back(2);v1.push_back(3);v1.push_back(4);v1.push_back(5);v1.push_back(6);v1.push_back(7);v1.push_back(8);print_vector(v1);//insert以后,发生了扩容,it失效了,因为it指向旧空间	解决:更新it//尽管我们在insert函数里更新了pos,但是pos是it的形参拷贝,pos改变不影响it,//就算传参为&,但是begin()就传不了,因为begin是传值返回,返回临时变量具有常性,//就得加const,就矛盾了//如果想要继续通过迭代器操作vector中的元素,只需给it重新赋值即可vector<int>::iterator it = v1.begin() + 3;cout << *it << endl;v1.insert(it, 40);print_vector(v1);cout << *it << endl;}//测试7 > ://1 2 3 4 5 6 7 8//4//1 2 3 40 4 5 6 7 8//- 572662307

erase导致的失效:
erase删除pos位置元素后,pos位置之后的元素会往前搬移,没有导致底层空间的改变,理论上讲迭代器不应该会失效,但是:如果pos刚好是最后一个元素,删完之后pos刚好是end的位置,而end位置是没有元素的,那么pos就失效了。因此删除vector中任意位置上元素时,vs就认为该位置迭代器失效了

iterator erase(iterator pos) {assert(pos >= _start);assert(pos < _finish);iterator it = pos+1;while (it < _finish) {*(it - 1) = *it;it++;}_finish--;return pos;}void test_vector8() {//迭代器失效2:删除偶数vector<int> v1;v1.push_back(1);v1.push_back(2);v1.push_back(3);v1.push_back(4);v1.push_back(4);v1.push_back(5);print_vector(v1);vector<int>::iterator it = v1.begin();while (it!=v1.end()){if (*it % 2 == 0) {v1.erase(it);}++it;解决:返回指向删除元素位置下一个的迭代器//if (*it % 2 == 0) {//	it = v1.erase(it);//}//else {//	++it;//}}print_vector(v1);}//测试8 > ://1 2 3 4 4 5//1 3 4 5

2.5使用memcpy拷贝问题

void reserve(size_t n) {int len = size();if (n > capacity()) {T* tmp = new T[n];//memcpy(tmp, _start, len * sizeof(T));for (size_t i = 0; i < len; i++){tmp[i] = _start[i];}delete[] _start;_start = tmp;_finish = _start + len;_endOfStorage = _start + n;}}vector<string> v;v.push_back("1111");v.push_back("2222");v.push_back("3333");v.push_back("4444");//当T是string等自定义深拷贝容器时,memcpy是浅拷贝,可能会引起内存泄漏甚至程序崩溃//解决,用for直接赋值代替memcpyv.push_back("5555");
1. memcpy 是内存的二进制格式拷贝将一段内存空间中内容原封不动的拷贝到另外一段内存空间中
2. 如果拷贝的是自定义类型的元素, memcpy 既高效又不会出错,但如果拷贝的是自定义类型元素,并且自定义类型元素中涉及到资源管理时,就会出错,因为memcpy 的拷贝实际是浅拷贝

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

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

相关文章

STM32应用开发——使用PWM+DMA驱动WS2812

STM32应用开发——使用PWMDMA驱动WS2812 目录 STM32应用开发——使用PWMDMA驱动WS2812前言1 硬件介绍1.1 WS2812介绍1.1.1 芯片简介1.1.2 引脚描述1.1.3 工作原理1.1.4 时序1.1.5 传输协议 1.2 电路设计 2 软件编程2.1 软件原理2.2 测试代码2.2.1 底层驱动2.2.2 灯效应用 2.3 运…

leetcode二叉树相关题目

目录 二叉树的建立整数数组转二叉树Object数组转二叉树 二叉树的遍历leetcode94.二叉树的中序遍历leetcode144.二叉树的前序遍历 二叉树的建立 整数数组转二叉树 下面只是一个简单的示例&#xff0c;没考虑某个子树为空的情况。把{1, 2, 3, 21, 22, 31, 32} 转变为一个二叉树…

新兴AI技术及其创业机会

量子计算与AI 量子计算是未来计算技术的前沿&#xff0c;它通过量子比特进行信息处理&#xff0c;相较于传统计算机&#xff0c;量子计算在处理复杂问题上有着天然的优势。将量子计算与AI结合&#xff0c;可以极大提升AI模型训练的效率和处理数据的能力。 创业机会&#xff1a…

基于NXP的ISELED开发环境搭建

目录 前言一、获取S32K SDK ISELED driver二、安装S32K SDK ISELED driverISELED文件说明三、ISELED工程介绍方案框图:图形化界面配置注意事项前言 NXP S32K ISELED 32位Arm Cortex-M微控制器 (MCU) 包括一种全新的通信协议 (ISELED),用于控制汽车和工业照明应用中的静态和动…

简述前端开发全景:从基础到未来的语言与趋势解析

前端开发概述 前端开发指的是创建网站或应用程序中用户可以直接看到和与之交互的部分。前端开发的主要目标是通过编写代码来制作用户界面&#xff0c;确保信息以易于理解和互动的方式展示给用户。 HTML和CSS HTML&#xff1a;HTML是构建网页的基础&#xff0c;负责定义网页的…

系统IO函数接口

目录 前言 一. man手册 1.1 man手册如何查询 1.2 man手册基础 二.系统IO函数接口 三.open打开文件夹 3.1 例1 open打开文件 3.2 open打开文件代码 3.3 例2 创建文件 四.write写文件 4.1 write写文件 五. read读文件 5.1 read读文件与偏移 5.2 偏移细节 5.3 read读文件代码 六.复…

3.5网安学习第三阶段第五周回顾(个人学习记录使用)

本周重点 ①SSRF服务器端请求伪造 ②序列化和反序列化 ③Vaudit代码审计 本周主要内容 ①SSRF服务器端请求伪造 一、概述 SSRF: server site request forgery (服务器端请求伪造)。 SSR: 服务端请求&#xff0c;A服务器通过函数向B服务器发送请求。 SSRF发生的前提条件…

Flutter动画笔记---总结

三种情况&#xff1a;第一种情况&#xff1a;隐式动画&#xff0c;全自动动画&#xff08;属于内部封装好了&#xff0c;只需要几行代码&#xff0c;就可以实现非常强大的效果&#xff09;第二种情况&#xff1a;显示动画&#xff0c;手动控制的动画&#xff08;提供自定义选择…

【ARM 嵌入式 C 字符串系列 23 -- 返回从父字符串找到相同子字符串的个数】

请阅读【嵌入式开发学习必备专栏 】 文章目录 返回从父字符串找到相同子字符串的个数 返回从父字符串找到相同子字符串的个数 在 C 语言中&#xff0c;可以编写一个自定义函数来计算一个父字符串&#xff08;haystack&#xff09;中相同子字符串&#xff08;needle&#xff09…

蓝桥杯备考随手记: practise04

问题描述: 小明被不明势力劫持。后莫名其妙被扔到 X 星站再无问津。小明得知每天都有飞船飞往地球&#xff0c;但需要 1 元的船票&#xff0c;而他却身无分文。他决定在 X 星站打工。好心的老板答应包食宿&#xff0c;第 1 天给他 1 元钱。并且&#xff0c;以后的每一天都比前…

《QT实用小工具·三》偏3D风格的异型窗体

1、概述 源码放在文章末尾 可以在窗体中点击鼠标左键进行图片切换&#xff0c;项目提供了一些图片素材&#xff0c;整体风格偏向于3D类型&#xff0c;也可以根据需求自己放置不同的图片。 下面是demo演示&#xff1a; 项目部分代码如下所示&#xff1a; 头文件部分&#xff…

Linux安装Tomcat保姆级教程

文章目录 前言一、安装JDK二、Tomcat下载三、Tomcat安装1.创建Tomcat的安装目录2.切换到Tomcat的安装目录3.上传Tomcat安装包4.解压缩5.切换到安装好的tomcat的bin目录6.启动tomcat7.网络请求测试 四、外部电脑访问nginx设置方法一&#xff1a;关闭防火墙方法二&#xff1a;添加…

Java反射系列(3):从spring反射工具ReflectionUtils说起

目录 传送门 兼容性引发的"血案" ReflectionUtils的原理 目的有三 ReflectionUtils的API使用 Method getAllDeclaredMethods findMethod invokeMethod Field getDeclaredFields findField getField makeAccessible Constructor accessibleConstructo…

Spring IoCDI(2)

IoC详解 通过上面的案例, 我们已经知道了IoC和DI的基本操作, 接下来我们来系统地学习Spring IoC和DI的操作. 前面我们提到的IoC控制反转, 就是将对象的控制权交给Spring的IoC容器, 由IoC容器创建及管理对象. (也就是Bean的存储). Bean的存储 我们之前只讲到了Component注解…

SAP Fiori开发中的JavaScript基础知识10 - 变量作用域,变量提升

1. 背景 本文将会介绍JavaScript中两个相对复杂的概念&#xff0c;也即作用域和变量提升。这个概念在JavaScript中的设计和ABAP中的设计区别还是比较大的&#xff0c;特别是变量提升部分。第一次接触JavaScript的同学&#xff0c;要注意理解和区分。 2. 作用域 在JavaScript…

vscode安装

&#x1f308;个人主页&#xff1a;Rookie Maker &#x1f3c6;&#x1f3c6;关注博主&#xff0c;随时获取更多关于IT的优质内容&#xff01;&#x1f3c6;&#x1f3c6; &#x1f600;欢迎来到小田代码世界~ &#x1f601; 喜欢的小伙伴记得一键三连哦 ૮(˶ᵔ ᵕ ᵔ˶)ა …

商场促销--策略模式

1.1 商场收银软件 package com.lhx.design.pattern.test;import java.util.Scanner;public class Test {public static void main(String[] args){System.out.println("**********************************************"); System.out.println("《大话设计模式…

vue3鼠标向下滑动,导航条改变背景颜色和logo的封装

代码中使用了element-plus组件&#xff0c;需先安装 向下滑动前 向下滑动后&#xff08;改变了logo 字体 背景颜色&#xff09; <script lang"ts" setup> import router from /router; import { ArrowDown } from element-plus/icons-vue import { ref, …

【tensorflow框架神经网络实现鸢尾花分类—优化器】

文章目录 1、前言2、神经网络参数优化器2.1、SGD2.2、SGDM2.3、Adagrad2.4、RMSProp2.5、Adam 3、实验对比不同优化器4、结果对比 1、前言 此前&#xff0c;在【tensorflow框架神经网络实现鸢尾花分类】一文中使用梯度下降算法SGD&#xff0c;对权重 w w w和偏置 b b b进行更新…

如何在Windows上安装SSH

SSH&#xff08;Secure Shell&#xff09;协议是一种强大且安全的网络协议&#xff0c;它为用户提供了一种加密的方式来远程访问和管理终端设备。在Windows操作系统中&#xff0c;安装和配置SSH服务是一个相对直接的过程&#xff0c;可以让你享受到SSH带来的便利和安全性。下面…