当前位置: 首页 > news >正文

【C++】STL——vector底层实现

目录

💕 1.vector三个核心

💕2.begin函数,end函数的实现(简单略讲)

💕3.size函数,capacity函数的实现 (简单略讲)

💕4.reserve函数实现 (细节详见)

💕5.resize函数实现(简单略讲,纯小计算)

💕6.其他功能函数实现(略讲,都是顺序表那一套没有改变) 

💕7.整体代码实现

💕8.底层模拟测试 .cpp

💕9.完结 


一个人的坚持到底有多难 

 

 声明:此文内容基于此文章->:【C++】STL——vector的使用

💕 1.vector三个核心

在vector中,核心成员并不是我们在数据结构实现的顺序表,如size,capacity,data,而是下面三个->:

#pragma once
#include<iostream>
#include<assert.h>
using namespace std;
namespace yz
{template<class T>class vector{typedef T* iterator;typedef const T* const_iterator;public:private:iterator _start = nullptr;iterator _finish = nullptr;iterator _end_of_storage = nullptr;};}

我们把元素的地址T*,命名为迭代器类型,iterator

接下来分别是顺序表起始位置的地址,顺序表的 size 用 _finish 来表示,顺序表的capacity用_end_of_storage来表示

💕2.begin函数,end函数的实现(简单略讲)

我们知道vector库中的begin函数与end函数返回的虽然是迭代器,但是可以像指针一样使用,因此我们可以很好的实现,如下->:

	iterator begin(){return _start;}iterator end(){return _finish;}const_iterator begin()const{return _start;}const_iterator end()const{return _finish;}

💕3.size函数,capacity函数的实现 (简单略讲)

size函数与capacity函数的实现更是简单,直接用指针相减即可

	size_t size(){return _finish - _start;}size_t capacity(){return _end_of_storage - _start;}

💕4.reserve函数实现 (细节详见)

代码看不懂的请往下看图片讲解

	//reserve预留空间T* reserve(size_t n){size_t old_size = size();if (n > capacity()){T* tep = new T[n+1];//开辟n个空间,+1是为了单独考虑string//将内容复制过去for (int i = 0; i < size(); i++){tep[i] = _start[i];}delete[] _start;_start = tep;_finish = _start + old_size;_end_of_storage = _start + n;tep = nullptr;}return _start;}

我们知道,capacity函数开辟的新空间只会增大,不会缩小,而开辟新空间我们需要做的第一件事就是转移数据


这里需要先思考下如何转移,如果用strcpy只可以转移string类,那怎么办?用memmove吗?

不,memmove的复制时一个字节一个字节复制过去的,虽然复制int,double时没有问题,但如果复制的是stirng类型,我们知道,string类的成员变量是字符串首地址,在使用memmove复制时字符串的首地址原封不动的复制了过去,这就会造成我们在释放旧空间后,白进行了memmove的复制,这是不可取的,所以我们要用到for循环转移数据,下面有图->:


转移数据思考完了,我们接着思考为什么要old_size,我们拷贝完数据后,需要转移的就是三大核心,start,finish,和end_of_storage,那么我们将数据转移后,释放掉原来的旧空间,就会导致finish和end_of_storage指向的是野指针,所以我们需要保留原来的old_size,这样才能让finish指向正确的位置

💕5.resize函数实现(简单略讲,纯小计算)

//resize预留空间
T* resize(size_t n,const T& val)
{if (n > size()){reserve(n);//先开辟出足够的空间size_t newsize = n - size();while (newsize > 0){*(_finish++) = val;newsize--;}}return _start;
}

💕6.其他功能函数实现(略讲,都是顺序表那一套没有改变) 

//判断空
bool empty()
{if (size() == 0){return true;}
}
//尾插
void push_back(const T& x)
{if (size() == capacity()) {size_t newcapacity = capacity() == 0 ? 4 : 2 * capacity();reverse(newcapacity);}*_finish = x;_finish++;
}
//尾删
void pop_back()
{empty();*_finish = 0;_finish--;
}
//指定位置插入
void insert(iterator pos, const T& val)
{assert(pos >= _start && pos <= _finish);if (size() == capacity()) {size_t count = pos - _start;size_t newcapacity = capacity() == 0 ? 4 : 2 * capacity();reverse(newcapacity);pos = _start + count;}T* tep = _finish;while (tep >= pos){*(tep) = *(tep - 1);tep--;}*(pos) = val;_finish++;
}
void erase(iterator pos)
{assert(pos >= _start && pos < _finish);empty();_finish--;while (pos < _finish){*(pos) = *(pos + 1);pos++;}
}

💕7.整体代码实现

#pragma once
#include<iostream>
#include<assert.h>
using namespace std;
namespace yz
{template<class T>class vector{public:typedef T* iterator;typedef const T* const_iterator;iterator begin(){return _start;}iterator end(){return _finish;}const_iterator begin()const{return _start;}const_iterator end()const{return _finish;}size_t size(){return _finish - _start;}size_t capacity(){return _end_of_storage - _start;}//reserve预留空间T* reserve(size_t n){size_t old_size = size();if (n > capacity()){T* tep = new T[n+1];//开辟n个空间,+1是为了单独考虑string//将内容复制过去for (int i = 0; i < size(); i++){tep[i] = _start[i];}delete[] _start;_start = tep;_finish = _start + old_size;_end_of_storage = _start + n;tep = nullptr;}return _start;}//resize预留空间T* resize(size_t n,const T& val){if (n > size()){reserve(n);//先开辟出足够的空间size_t newsize = n - size();while (newsize > 0){*(_finish++) = val;newsize--;}}return _start;}//判断空bool empty(){if (size() == 0){return true;}}//尾插void push_back(const T& x){if (size() == capacity()) {size_t newcapacity = capacity() == 0 ? 4 : 2 * capacity();reverse(newcapacity);}*_finish = x;_finish++;}//尾删void pop_back(){empty();*_finish = 0;_finish--;}//指定位置插入void insert(iterator pos, const T& val){assert(pos >= _start && pos <= _finish);if (size() == capacity()) {size_t count = pos - _start;size_t newcapacity = capacity() == 0 ? 4 : 2 * capacity();reverse(newcapacity);pos = _start + count;}T* tep = _finish;while (tep >= pos){*(tep) = *(tep - 1);tep--;}*(pos) = val;_finish++;}void erase(iterator pos){assert(pos >= _start && pos < _finish);empty();_finish--;while (pos < _finish){*(pos) = *(pos + 1);pos++;}}private:iterator _start = nullptr;iterator _finish = nullptr;iterator _end_of_storage = nullptr;};}

💕8.底层模拟测试 .cpp

#define _CRT_SECURE_NO_WARNINGS 
#include"vector.h"
int main()
{yz::vector<int> a1;/*a1.resize(200,3);cout<<a1.size()<<' '<<a1.capacity();a1.empty();*/a1.insert(a1.begin(), 99);a1.insert(a1.begin(), 88);a1.push_back(0);a1.push_back(20);a1.push_back(28);a1.pop_back();a1.erase(a1.begin());a1.erase(a1.end()-1);a1.resize(200, 5);a1.reserve(300);yz::vector<int> a2;if (a2.empty()){cout << "空" << endl;}for (auto e : a1){cout << e << ' ';}}

💕9.完结 

相关文章:

【C++】STL——vector底层实现

目录 &#x1f495; 1.vector三个核心 &#x1f495;2.begin函数&#xff0c;end函数的实现&#xff08;简单略讲&#xff09; &#x1f495;3.size函数&#xff0c;capacity函数的实现 &#xff08;简单略讲&#xff09; &#x1f495;4.reserve函数实现 &#xff08;细节…...

数据结构初探:链表之单链表篇

本文图皆为作者手绘,所有代码基于vs2022运行测试 系列文章目录 数据结构初探:顺序表篇 文章目录 系列文章目录前言一、链表基础概念二、链表的分类简化边界条件处理使代码更清晰简洁提高程序稳定性 1.单链表(不带头不循环的单链表);1.1存储结构;1.2准备工作1.3链表增删查改的实…...

介绍一下Mybatis的底层原理(包括一二级缓存)

表面上我们的就是Sql语句和我们的java对象进行映射&#xff0c;然后Mapper代理然后调用方法来操作数据库 底层的话我们就涉及到Sqlsession和Configuration 首先说一下SqlSession&#xff0c; 它可以被视为与数据库交互的一个会话&#xff0c;用于执行 SQL 语句&#xff08;Ex…...

Linux基础 ——tmux vim 以及基本的shell语法

Linux 基础 ACWING y总的Linux基础课&#xff0c;看讲义作作笔记。 tmux tmux 可以干嘛&#xff1f; tmux可以分屏多开窗口&#xff0c;可以进行多个任务&#xff0c;断线&#xff0c;不会自动杀掉正在进行的进程。 tmux – session(会话&#xff0c;多个) – window(多个…...

64位的谷歌浏览器Chrome/Google Chrome

64位的谷歌浏览器Chrome/Google Chrome 在百度搜索关键字:chrome&#xff0c;即可下载官方的“谷歌浏览器Chrome/Google Chrome”&#xff0c;但它可能是32位的&#xff08;切记注意网址&#xff1a;https://www.google.cn/....&#xff0c; 即&#xff1a;google.cn&#xff…...

jetson编译torchvision出现 No such file or directory: ‘:/usr/local/cuda/bin/nvcc‘

文章目录 1. 完整报错2. 解决方法 1. 完整报错 jetson编译torchvision,执行python3 setup.py install --user遇到报错 running build_ext error: [Errno 2] No such file or directory: :/usr/local/cuda/bin/nvcc完整报错信息如下&#xff1a; (pytorch) nxnx-desktop:~/Do…...

多线程创建方式三:实现Callable接口

实现Callable第三种方式存在的原因 作用&#xff1a;可以返回线程执行完毕后的结果。 前两种线程创建方式都存在的一个问题&#xff1a;假如线程执行完毕后有一些数据需要返回,他们重写的run方法均不能直接返回结果。 如何实现 ● JDK 5.0提供了Callable接口和FutureTask类来…...

Linux下的编辑器 —— vim

目录 1.什么是vim 2.vim的模式 认识常用的三种模式 三种模式之间的切换 命令模式和插入模式的转化 命令模式和底行模式的转化 插入模式和底行模式的转化 3.命令模式下的命令集 光标移动相关的命令 复制粘贴相关命令 撤销删除相关命令 查找相关命令 批量化注释和去…...

Docker技术相关学习二

一、Docker简介 1.Docker之父Solomon Hykes形容docker就像传统的货运集装箱。 2.docker的特点和优势&#xff1a; 轻量级虚拟化&#xff1a;Docker容器相较于传统的虚拟机更加的轻量和高效&#xff0c;能够快速的启动和停止来节省系统资源。 一致性&#xff1a;确保应用程序在不…...

【人工智能】多模态学习在Python中的应用:结合图像与文本数据的深度探索

《Python OpenCV从菜鸟到高手》带你进入图像处理与计算机视觉的大门! 解锁Python编程的无限可能:《奇妙的Python》带你漫游代码世界 多模态学习是人工智能领域的一个重要研究方向,旨在通过结合多种类型的数据(如图像、文本、音频等)来提高模型的性能。本文将深入探讨多模…...

【MySQL】常用语句

目录 1. 数据库操作2. 表操作3. 数据操作&#xff08;CRUD&#xff09;4. 高级查询5. 索引管理6. 用户与权限7. 数据导入导出8. 事务控制9. 其他实用语句注意事项 如果这篇文章对你有所帮助&#xff0c;渴望获得你的一个点赞&#xff01; 1. 数据库操作 创建数据库 CREATE DATA…...

Docker网络基础

一、Docker网络基础 1.docker安装后会自动创建3中网络&#xff0c;分别为bridge host none docker network ls 2.docker原生bridge网络&#xff1a; docker安装时会创建一个名为docker0的linux bridge,新建的容器会自动桥接到这个接口 bridge模式下没有公有ip,只有宿主机可以…...

重新刷题求职2-DAY2

977. 有序数组的平方 给你一个按 非递减顺序 排序的整数数组 nums&#xff0c;返回 每个数字的平方 组成的新数组&#xff0c;要求也按 非递减顺序 排序。 示例 1&#xff1a; 输入&#xff1a;nums [-4,-1,0,3,10] 输出&#xff1a;[0,1,9,16,100] 解释&#xff1a;平方后…...

[STM32 标准库]EXTI应用场景 功能框图 寄存器

一、EXTI 外部中断在嵌入式系统中有广泛的应用场景&#xff0c;如按钮开关控制&#xff0c;传感器触发&#xff0c;通信接口中断等。其原理都差不多&#xff0c;STM32会对外部中断引脚的边沿进行检测&#xff0c;若检测到相应的边沿会触发中断&#xff0c;在中断中做出相应的处…...

Slint的学习

Slint是什么 Slint是一个跨平台的UI工具包&#xff0c;支持windows,linux,android,ios,web&#xff0c;可以用它来构建申明式UI,后端代码支持rust,c,python,nodejs等语言。 开源地址&#xff1a;https://github.com/slint-ui/slint 镜像地址&#xff1a;https://kkgithub.com/…...

STM32 DMA+AD多通道

接线图 代码配置 ADC单次扫描DMA单次转运模式 uint16_t AD_Value[4]; //DMAAD多通道 void DMA_Config(void) {//定义结构体变量 GPIO_InitTypeDef GPIO_InitStructure;//定义GPIO结构体变量 ADC_InitTypeDef ADC_InitStructure; //定义ADC结构体变量 DMA_InitTypeDef DMA_In…...

如何构建ObjC语言编译环境?构建无比简洁的clang编译ObjC环境?Windows搭建Swift语言编译环境?

如何构建ObjC语言编译环境? 除了在线ObjC编译器&#xff0c;本地环境Windows/Mac/Linux均可以搭建ObjC编译环境。 Mac自然不用多说&#xff0c;ObjC是亲儿子。(WSL Ubuntu 22.04) Ubuntu可以安装gobjc/gnustep和gnustep-devel构建编译环境。 sudo apt-get install gobjc gnus…...

【C语言】指针详解:概念、类型与解引用

博客主页&#xff1a; [小ᶻ☡꙳ᵃⁱᵍᶜ꙳] 本文专栏: C语言 文章目录 &#x1f4af;前言&#x1f4af;指针的基本概念1. 什么是指针2. 指针的基本操作 &#x1f4af;指针的类型1. 指针的大小2. 指针类型与所指向的数据类型3. 指针类型与数据访问的关系4. 指针类型的实际意…...

VoIP中常见术语

在 VoIP&#xff08;Voice over Internet Protocol&#xff0c;基于互联网协议的语音传输&#xff09;技术中&#xff0c;涉及许多专业术语。以下是常见术语及其含义&#xff1a; 1. 核心协议相关 SIP&#xff08;Session Initiation Protocol&#xff0c;会话发起协议&#xf…...

360嵌入式开发面试题及参考答案

解释一下 802.11ax 和 802.11ac/n 有什么区别 速度与带宽 802.11n 支持的最高理论速率为 600Mbps,802.11ac 进一步提升,单流最高可达 866.7Mbps,多流情况下能达到更高,如 1.3Gbps 等。而 802.11ax(Wi-Fi 6)引入了更多先进技术,理论最高速率可达 9.6Gbps,相比前两者有大…...

变量 varablie 声明- Rust 变量 let mut 声明与 C/C++ 变量声明对比分析

一、变量声明设计&#xff1a;let 与 mut 的哲学解析 Rust 采用 let 声明变量并通过 mut 显式标记可变性&#xff0c;这种设计体现了语言的核心哲学。以下是深度解析&#xff1a; 1.1 设计理念剖析 安全优先原则&#xff1a;默认不可变强制开发者明确声明意图 let x 5; …...

设计模式和设计原则回顾

设计模式和设计原则回顾 23种设计模式是设计原则的完美体现,设计原则设计原则是设计模式的理论基石, 设计模式 在经典的设计模式分类中(如《设计模式:可复用面向对象软件的基础》一书中),总共有23种设计模式,分为三大类: 一、创建型模式(5种) 1. 单例模式(Sing…...

css实现圆环展示百分比,根据值动态展示所占比例

代码如下 <view class""><view class"circle-chart"><view v-if"!!num" class"pie-item" :style"{background: conic-gradient(var(--one-color) 0%,#E9E6F1 ${num}%),}"></view><view v-else …...

Java线上CPU飙高问题排查全指南

一、引言 在Java应用的线上运行环境中&#xff0c;CPU飙高是一个常见且棘手的性能问题。当系统出现CPU飙高时&#xff0c;通常会导致应用响应缓慢&#xff0c;甚至服务不可用&#xff0c;严重影响用户体验和业务运行。因此&#xff0c;掌握一套科学有效的CPU飙高问题排查方法&…...

中医有效性探讨

文章目录 西医是如何发展到以生物化学为药理基础的现代医学&#xff1f;传统医学奠基期&#xff08;远古 - 17 世纪&#xff09;近代医学转型期&#xff08;17 世纪 - 19 世纪末&#xff09;​现代医学成熟期&#xff08;20世纪至今&#xff09; 中医的源远流长和一脉相承远古至…...

深入浅出深度学习基础:从感知机到全连接神经网络的核心原理与应用

文章目录 前言一、感知机 (Perceptron)1.1 基础介绍1.1.1 感知机是什么&#xff1f;1.1.2 感知机的工作原理 1.2 感知机的简单应用&#xff1a;基本逻辑门1.2.1 逻辑与 (Logic AND)1.2.2 逻辑或 (Logic OR)1.2.3 逻辑与非 (Logic NAND) 1.3 感知机的实现1.3.1 简单实现 (基于阈…...

基于Springboot+Vue的办公管理系统

角色&#xff1a; 管理员、员工 技术&#xff1a; 后端: SpringBoot, Vue2, MySQL, Mybatis-Plus 前端: Vue2, Element-UI, Axios, Echarts, Vue-Router 核心功能&#xff1a; 该办公管理系统是一个综合性的企业内部管理平台&#xff0c;旨在提升企业运营效率和员工管理水…...

MinIO Docker 部署:仅开放一个端口

MinIO Docker 部署:仅开放一个端口 在实际的服务器部署中,出于安全和管理的考虑,我们可能只能开放一个端口。MinIO 是一个高性能的对象存储服务,支持 Docker 部署,但默认情况下它需要两个端口:一个是 API 端口(用于存储和访问数据),另一个是控制台端口(用于管理界面…...

通过 Ansible 在 Windows 2022 上安装 IIS Web 服务器

拓扑结构 这是一个用于通过 Ansible 部署 IIS Web 服务器的实验室拓扑。 前提条件&#xff1a; 在被管理的节点上安装WinRm 准备一张自签名的证书 开放防火墙入站tcp 5985 5986端口 准备自签名证书 PS C:\Users\azureuser> $cert New-SelfSignedCertificate -DnsName &…...

es6+和css3新增的特性有哪些

一&#xff1a;ECMAScript 新特性&#xff08;ES6&#xff09; ES6 (2015) - 革命性更新 1&#xff0c;记住的方法&#xff0c;从一个方法里面用到了哪些技术 1&#xff0c;let /const块级作用域声明2&#xff0c;**默认参数**&#xff1a;函数参数可以设置默认值。3&#x…...