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

深度学习 vector 之模拟实现 vector (C++)

1. 基础框架

这里我们有三个私有变量,使用 _finish - _start 代表 _size,_end_of_storage - _start 代表 _capacity,并且使用到了模版,可以灵活定义存储不同类型的 vector,这里将代码量较小的函数直接定义在类的内部使其成为内联函数

namespace bit
{template<class T>class vector{public:typedef T* iterator;typedef const T* const_iterator;//迭代器iterator begin(){return _start;}iterator end(){return _finish;}//const 迭代器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;}//可读可写T& operator[](size_t i){assert(i < size());return _start[i];}//只读const T& operator[](size_t i) const{assert(i < size());return _start[i];}bool empty(){return _start == _finish;}private:iterator _start = nullptr;iterator _finish = nullptr;iterator _end_of_storage = nullptr;};
}

2. 核心接口

2.1 增删与扩容

增删接口主要讲解的有尾删尾删、插入删除以及扩容

2.1.1 push_back & pop_back

尾插尾删

这里的尾插首先要判断是否需要扩容,然后在数据尾部插入数据即可

尾删则只需要保证所给的位置不超出范围后直接 --_finish 即可

//尾插
void push_back(const T& x)
{if (finish == _end_of_storage){reserve(capacity() == 0 ? 4 : capacity() * 2);}*finish = x;finish++;
}
//尾删
void pop_back()
{assert(!empty());--_finish;
}

2.1.2 insert

在指定位置插入数据

这里首先判断是否需要扩容,然后将指定位置pos之后的数据均向后移动,最后插入数据即可,这里需要注意的是在扩容后原来的pos位置就会失效,也就是迭代器失效,这里就相当于成为了野指针,所以解决方法是将原来的位置记录下来在扩容后更新即可

void insert(iterator pos, const T& x)
{assert(pos >= _start);assert(pos <= _finish);if (_finish == _end_of_stroage){size_t len = pos - _start;reserve(capacity() == 0 ? 4 : 2 * capacity());pos = _start + len;}iterator end = _finish - 1;while (pos != end){*(end + 1) = *end;--end;}++_finish;
}

2.1.3 erase

删除指定位置数据

这里删除就是保证所给位置在范围内然后直接将要删除的位置之后的数据覆盖到原来位置即可,需要注意的是在erase操作后也会出现迭代器失效,所以要继续使用pos的话需要记录原来的位置然后更新

//erase后的迭代器也看做是失效的
void erase(iterator pos)
{assert(pos >= _start);assert(pos < _finish);iterator it = pos + 1;while (it != end()){*(it + 1) = *it;it++;}_finish--;
}

2.1.4 resize 

初始化指定长度的指定数据

这里主要注意的是要分三种情况:1. n < size(),这时就直接缩容即可;2. size() < n < capacity(),这里就直接插入数据,不用扩容;3. capacity() < n,这里需要扩容后插入数据

//这里的T可以是string类也可以是内置类型int等,string类有自己的默认构造函数
//内置类型同样有自己的默认构造函数
void resize(size_t n, T val = T())
{if (n < size())//n小于_size则缩容{_finish = _start + n;}else{reserve(n);//如果n超过_capacity则扩容while (_finish != _start + n){*_finish = val;++_finish;}}
}

2.1.5 reserve 

判断空间是否充足后进行扩容

扩容操作就是判断原容量是否足够插入新数据,不够则二倍扩容即可,这里的注意事项有:1. 要将原来的size()保存成为old_size,以保证之后的_finish在计算时不会出现野指针的情况,因为如果不保存原来的size(),那么在之后size()就会更新成为新的size(),这里计算就会出现差错

2. 注意memcpy是浅拷贝,在处理内置类型int、double这样的数据不会出错,但是如果是string或者vector这样需要深拷贝类型的数据就会出错导致内存泄漏,解决方法就是使用其本身的赋值运算,这样可以兼顾二者

//扩容
void reserve(size_t n)
{if (n > capacity()){size_t old_size = size();T* tmp = new T[n];//memcpy(tmp, _start, old_size * sizeof(T));//拷贝数据for (size_t i = 0; i < old_size; i++){tmp[i] = _start[i];}delete[] _start;//释放旧空间_start = tmp;//指向新空间_finish = tmp + old_size;//tmp(新的) + _finish(原来) - _start(原来)_end_of_storage = tmp + n;}
}

2.2 拷贝构造

2.2.1 构造函数与析构函数

这里涉及的知识点有:

1. 类模版的成员函数仍然可以是函数模版

2. 在迭代器区间构造的函数时可以使用函数模版,这样可以使用任意容器的迭代器初始化,例如链表

//直接走初始化列表,如果没有则使用缺省值
vector()
{}
//C++11强制生成默认构造
//vector() = default;//类模版的成员函数仍然可以是函数模版
//迭代器区间构造
//可以使用任意容器的迭代器初始化
//例如链表
template<class InputIterator>
vector(InputIterator first, InputIterator last)
{while (first != last){push_back(*first);first++;}
}//使用n个val初始化
vector(size_t n, const T& val = T())
{reserve(n);for (size_t i = 0; i < n; i++){ push_back(val);}
}~vector()
{if (_start){delete[] _start;_start = _finish = _end_of_storage;}
}

2.2.2 拷贝构造函数 

这里直接只用范围for进行深拷贝操作,简单便捷,并且提前保存空间减少扩容带来的消耗

//拷贝构造
vector(const vector<T>& v)
{reserve(v.size());for (auto& e : v){//这里默认有一个this指针//直接完成了深拷贝的工作push_back(e);}
}

2.3 赋值重载 

这里涉及了两种写法:

1. 自己完成赋值:人为进行赋值的操作,过程比较清晰

2. 交给编译器完成赋值:交给编译器直接完成交换以达到赋值的目的,操作更加简便

//赋值重载
1、传统写法
void clear()
{_finish = _start;
}vector<T>& operator=(const vector<T>& v)//传地址
{if (this != &v){clear();reserve(v.size());for (auto& e : v){push_back(e);}}return *this;
}//2、现代写法
void swap(const vector<T> v)
{std::swap(_start, v._start);std::swap(_finish, v._finish);std::swap(_end_of_storage, v._end_of_storage);
}
vector<T>& operator=(const vector<T> v)//传值
{swap(v);return *this;
}

3. 常见问题

3.1 迭代器失效

这里的迭代器失效有两种情况:

1. 扩容后迭代器失效:这里首先了解扩容的原理是开辟一个原来空间二倍的空间,将原空间数据拷贝到扩容后的空间,然后释放原空间,所以由于pos在扩容后仍然指向的是原空间,而原空间已经释放,所以导致了类似野指针的效果,也就是第一种迭代器失效

2. 未扩容但是挪动数据导致的迭代器失效:即在使用原来pos完成挪动数据的操作后,pos已经不指向原来的位置,这时如果仍然想要访问原来位置就会导致迭代器失效

解决方法:保存原来的迭代器指向的位置或者相对位置,然后在扩容或者挪动数据之后更新pos指向的位置即可

void insert(iterator pos, const T& x)
{assert(pos >= _start);assert(pos <= _finish);//1.扩容,注意避免迭代器失效,即pos在扩容后仍然指向之前的空间//在之后对新空间的操作时会失效,类似野指针,就是迭代器失效//这里使用相对位置来避免迭代器失效//还需要注意,在insert之后的迭代器是失效的,不可以直接继续访问,但是可以在更新后访问//2.不扩容,但是由于数据的挪动导致p不再指向原来的位置,也看做迭代器失效//关于迭代器失效的处理方法就是接收操作之后的迭代器,然后对更新后的迭代器进行操作即可if (_finish == _end_of_stroage){size_t len = pos - _start;reserve(capacity() == 0 ? 4 : 2 * capacity());pos = _start + len;}iterator end = _finish - 1;while (pos != end){*(end + 1) = *end;--end;}++_finish;
}
//erase后的迭代器也看做是失效的
void erase(iterator pos)
{assert(pos >= _start);assert(pos < _finish);iterator it = pos + 1;while (it != end()){*(it + 1) = *it;it++;}_finish--;
}

3.2 浅拷贝 

浅拷贝就是指两个指针指向同一块空间,这时如果一个指针对该空间进行释放或者其他操作会影响另一个指针导致内存泄漏等后果,解决方法很简单就是深拷贝使两指针指向不同的空间然后使其数据保持一致即可

//扩容
void reserve(size_t n)
{if (n > capacity()){size_t old_size = size();T* tmp = new T[n];//memcpy(tmp, _start, old_size * sizeof(T));//拷贝数据//这里的T如果是string或者vector类型这种需要深拷贝的类型// 则需要赋值进行拷贝数据,否则浅拷贝会导致内存泄漏//这里调用的赋值就是string/vector的赋值,就是深拷贝for (size_t i = 0; i < old_size; i++){tmp[i] = _start[i];}delete[] _start;//释放旧空间_start = tmp;//指向新空间_finish = tmp + old_size;//tmp(新的) + _finish(原来) - _start(原来)_end_of_storage = tmp + n;}
}

 3.3 类型转换

这个问题是因为由于给出的代码编译器不知道该代码是类型还是变量,所以导致识别不出来,解决方法就是改为 auto 自动转换或者前面加上 typename 来告诉编译器即可

template<class T>
void print_vector(const vector<T>& v)
{//编译器无法确定此处的const_iterator是类型还是静态成员变量//所以规定不能从未实例化的类模版内取东西,需要程序员自己规定//即加一个 typename 来表示这里的const_iterator是类型即可typename vector<T>::const_iterator it = v.begin();while (it != v.end()){cout << *it << " ";it++;}cout << endl;for (auto e : v){cout << e << " ";}cout << endl;
}

 

相关文章:

深度学习 vector 之模拟实现 vector (C++)

1. 基础框架 这里我们有三个私有变量&#xff0c;使用 _finish - _start 代表 _size&#xff0c;_end_of_storage - _start 代表 _capacity&#xff0c;并且使用到了模版&#xff0c;可以灵活定义存储不同类型的 vector&#xff0c;这里将代码量较小的函数直接定义在类的内部使…...

关于LLC知识10

在LLC谐振腔中能够变化的量 1、输入电压 2、Rac&#xff08;负载&#xff09; 所以增益曲线为红色&#xff08;Rac无穷大&#xff09;已经是工作的最大极限了&#xff0c;LLC不可能工作在红色曲线之外 负载越重时&#xff0c;增益曲线越往里面 假设&#xff1a; 输入电压…...

最长的严格递增或递减子数组

给你一个整数数组 nums 。 返回数组 nums 中 严格递增 或 严格递减 的最长非空子数组的长度。 示例 1&#xff1a; 输入&#xff1a;nums [1,4,3,3,2] 输出&#xff1a;2 解释&#xff1a; nums 中严格递增的子数组有[1]、[2]、[3]、[3]、[4] 以及 [1,4] 。 nums 中…...

【JavaEE】SpringBoot 统一功能处理:拦截器、统一数据返回与异常处理的综合应用与源码解析

目录 SpringBoot 统⼀功能处理拦截器拦截器快速⼊⻔拦截器详解拦截路径拦截器执⾏流程 登录校验定义拦截器注册配置拦截器 DispatcherServlet 源码分析(了解)初始化(了解) DispatcherServlet的初始化1. HttpServletBean.init()2. FrameworkServlet.initServletBean() WebApplic…...

I2C学习:上拉电阻选取

一&#xff0e;I2C简介 I2C总线是由Philips公司开发的一种简单、双向二线制同步串行总线。I2C总线在使用时&#xff0c;需要接上拉电阻&#xff0c;这是因为I2C接口是开漏输出&#xff0c;如图1所示。 图1 I2C开漏输出 I2C有5种速度模式&#xff1a;标准&#xff08;100KHz&am…...

AC自动机-1

AC自动机&#xff08;Aho-Corasick Automaton&#xff09;是一种高效的多模式字符串匹配算法。它是由Alfred Aho和Margaret Corasick在1975年提出的。这种算法可以在一次扫描输入文本的情况下,同时查找多个模式串。 基本概念 Trie树 AC自动机是基于字典树数据结构构建的字典树…...

注解@Service@Component@Slf4j@Data

在Java中&#xff0c;这四个注解分别属于不同的用途和库&#xff0c;下面是它们各自的作用&#xff1a; Service&#xff1a; 这个注解通常用于Spring框架中&#xff0c;它用于标记服务层组件。在Spring中&#xff0c;服务层通常包含业务逻辑。当一个类被标记为Service&#xf…...

【Nodejs】六、express框架

目录 一、express 介绍 二、express 使用 2.1 express 下载 2.2 express 使用 三、express 路由 3.1 什么是路由 3.2 路由的使用 3.3 获取请求参数 3.4 获取路由参数 四、express 响应设置 五、express 中间件 5.1 什么是中间件 5.2 中间件的作用 5.3 中间件的类…...

进阶 pro max

最近搞了许多有趣的东西&#xff0c;比如自制rtos&#xff0c;速成数模电&#xff0c;学了一点点的AD&#xff0c;看着视频弄了HAL库&#xff0c;以及定时器和串口中断配合实现接收任意长度&#xff08;不超过缓冲值&#xff09;数据&#xff0c;还有配置hal库的freertosfafts …...

Agentic Security:一款针对LLM模型的模糊测试与安全检测工具

关于Agentic Security Agentic Security是一款针对LLM模型的模糊测试与安全检测工具&#xff0c;该工具可以帮助广大研究人员针对任意LLM执行全面的安全分析与测试。 请注意 Agentic Security 是作为安全扫描工具设计的&#xff0c;而不是万无一失的解决方案。它无法保证完全防…...

Spring Cloud Config 与 Spring Cloud Bus 来实现动态配置文件

要使用 Spring Cloud Config 与 Spring Cloud Bus 来实现动态配置文件&#xff0c;你可以按照以下步骤操作&#xff1a; ### 步骤 1: 添加依赖 首先&#xff0c;确保你的项目中添加了 Spring Cloud Config 客户端和 Bus 的依赖。对于 Maven 项目&#xff0c;pom.xml 文件应该…...

Qt:Qt背景

目录 1.Qt解释 2.Windows下开发GUI的方案 3.框架 4.Qt历史 4.Qt支持的平台 5.Qt版本 6.Qt案例 1.Qt解释 前端开发&#xff0c;分为网页前端开发&#xff08;Web)、桌面应用开发&#xff08;Windows、Linux&#xff09;、移动应用开发&#xff08;Android&#xff09;。Q…...

【数据结构】选择排序

&#x1f36c;个人主页&#xff1a;Yanni.— &#x1f308;数据结构&#xff1a;Data Structure.​​​​​​ &#x1f382;C语言笔记&#xff1a;C Language Notes &#x1f3c0;OJ题分享&#xff1a; Topic Sharing 目录 前言&#xff1a; 基本思想 直接选择排序 思路分…...

国产GD32单片机开发入门(二)GD32单片机详解

文章目录 一.概要二.单片机型号命名规则三.GD32F103系统架构四.GD32F103C8T6单片机启动流程五.GD32F103C8T6单片机主要外设资源六.单片机开发过程中查看芯片数据手册的必要性1.单片机外设资源情况2.GD32单片机内部框图3.GD32单片机管脚图4.GD32单片机每个管脚功能5.单片机功耗数…...

8个我平时每天都会看的网站,涵盖办公、娱乐、学习等

分享8个我平时每天都会看的网站&#xff0c;涵盖办公、娱乐、学习等多种类别&#xff0c;试过就知道有多好用&#xff01; 1、MyFreeMP3 tools.liumingye.cn/music/#/ 一个可以免费听歌的平台&#xff0c;不用充会员&#xff0c;里面收录了大多数的国内外知名流行歌手、乐队的…...

Vue2——父子之间间的调用

1、父组件给子组件传值使用props 父组件&#xff1a; <div><SonPage msg"通过props传递值---父>子" ></SonPage><h1>父组件</h1></div> 子组件 <div :style"{border: 1px solid red}"><h1>子组件…...

xfs Vs ext4?

xfs测试 ext4 测试 对比 XFS和EXT4都是Linux系统中广泛使用的文件系统&#xff0c;它们各有特点和优势&#xff0c;选择哪一个取决于你的具体需求和使用场景。下面是它们的主要特点&#xff1a; XFS: 由Silicon Graphics Inc.开发&#xff0c;最初用于SGI的IRIX系统。支持非…...

数据结构stack (笔记)

文章目录 1. 概念理解易混淆内容 2. 时间复杂度3. 实现方式4. 应用5. 内容出处 1. 概念理解 stack(中文名&#xff1a;堆栈、栈)&#xff1a;虽然它叫堆栈&#xff0c;但是它其实指的是栈&#xff0c;跟堆没啥关系。 栈的特性&#xff1a;先进后出、后进先出(这个过程就…...

SQL - 创建 表和数据库

创建和删除数据库 create database if not exists sql_store2; //创建 drop database if exists sql_store2; //删除 -- 创建数据库 create database if not exists sql_store2; drop database if exists sql_store2; 创建表 create table customers (someting); -- 创建表 cre…...

使用 Arch Linux 几个月有感 | 为什么我选择 Arch Linux ,Arch 的优缺点有什么 | 一些Linux发行版推荐

&#xff08;终端是 Yakuake &#xff0c;KDE 自带&#xff09; 一点碎碎念&#xff0c;可以跳过不看 几年前从 CentOS 接触的 Linux &#xff0c;试图搭建一个KMS服务器 但是失败了 &#xff0c;后来装过 Ubuntu Debian deepin Kali Kubuntu Manjaro&#xff0c;踩一路坑最后…...

SQLserver中的增删改查和数据类型

SQLserver增删查改语句 SQL Server 是一种关系数据库管理系统&#xff0c;用于存储、管理和检索数据。以下是一些基本的 SQL 语句&#xff0c;用于在 SQL Server 中执行增删查改操作&#xff1a; 插入数据&#xff08;Insert&#xff09; 插入完整行&#xff1a; INSERT INTO …...

个人收藏个性化、实用性、可玩性在线网站持续更新,与君共享

1.https://handraw.top/ 支持中文手绘效果的白板工具&#xff0c;比较怀旧复古风格 界面简单风 2.https://app.diagrams.net 流程图、UML图、网络图、组织结构图、思维导图等&#xff0c;比较专业 可导出图片 PDF HTLM等各种格式 3.https://www.processon.com 主要用于生成…...

win10蓝牙只能发送,无法接收

给win10升了级&#xff0c;到22H2&#xff0c;蓝牙出了问题 以前接收&#xff0c;就是默认直接就可以接收。现在只能发送&#xff0c;无法接收。 在网上找了很多办法都没奏效&#xff0c;目前的方法是&#xff0c; 每次接收&#xff0c;都要操作一次&#xff0c;而不是自动接…...

【论文阅读03】用于海洋物体检测的多注意力路径聚合网络

来源&#xff1a;用于海洋物体检测的多注意力路径聚合网络 |应用智能 (springer.com) 一、背景&#xff1a; 水下图像存在偏色、对比度低、能见度低等问题&#xff0c;使得海洋物体难以被探测到。这些都增加了海上目标探测的难度。 目前流行的检测器方法是基于卷积神经网络&…...

Linux 进程(2)

进程的回收 1.wait 原型 pid_t wait(int *status); 功能&#xff1a;该函数可以阻塞等待任意子进程退出 并回收该进程的状态。 一般用于父进程回收子进程状态。 参数&#xff1a;status 进程退出时候的状态 如果不关心其退出状态一般用NULL表示 如果要回收进程…...

[CSCCTF 2019 Qual]FlaskLight1

打开题目 右键查看一下源代码 看到提示&#xff0c;需要用GET方search函数...

layui table表单 checkbox选中一个其它也要选中

当我们选中其中一个商品的时候同类型的商品状态也要跟着改变 所以要在表单加载完成后去监听checkbox ,done:function (res) {console.log(详情表格数据,res)tableDetailList res.data;// 监听表格复选框选择table.on(checkbox( INST_SELECTORS.instLayFilters.unpaidTableDe…...

【pip镜像设置】pip使用清华镜像源安装

文章目录 问题&#xff1a;问题描述原因分析&#xff1a;PyPI&#xff08;Python Package Index&#xff09; PypI 镜像列表解决方案&#xff1a; 问题&#xff1a; 大家经常会使用 pip 进行python 的第三方库安装&#xff0c;但是&#xff0c;有时会出现 ERROR: Could not f…...

c++ 智能指针--std::shared_ptr

在C中&#xff0c;std::shared_ptr是智能指针的一种&#xff0c;它用于自动管理具有动态生命周期的对象。当std::shared_ptr的实例被销毁或重置时&#xff0c;它所指向的对象&#xff08;如果仍然存在&#xff09;将被自动删除&#xff08;调用delete&#xff09;&#xff0c;前…...

网络工程师学习笔记(二)

计算机网络概述——二 通信子网中转发节点的互联模式叫做子网的拓扑结构 常见的拓扑结构&#xff1a; 总线型(一条总干线上连接着多个终端) 特点&#xff1a;损坏一个节点会造成单点故障 星型&#xff08;中间一台服务器或者一各小型工作站周围都是计算机&#xff09; 特点…...

合肥做网站优化/做推广app赚钱的项目

有时因为病毒修改或人为删除了某个系统文件,造成系统无法正常运行的时候, 如果知道被修改或丢失的文件的文件名,我们就可以试着用光盘来修复,但是修复的时间很长,我们可以直接用expand命令来提取所需要的那个文件. 其用法如下: EXPAND [-r] Source DestinationEXPAND -r Source…...

创造一个网站/产品推广广告

Moved to http://blog.tangcs.com/2010/11/20/subversion/转载于:https://www.cnblogs.com/WarrenTang/archive/2010/11/20/1882582.html...

门户网站模板 图片/百度云搜索引擎官方入口

环境&#xff1a;windows7&#xff0c;MyEclipse10&#xff0c;maven3.3 相信有很多朋友在MyEclipse10中使用maven时会遇到添加中央仓库中无法找到的jar包&#xff0c;或者是添加自己打包好的jar包&#xff0c;这里就不在聒噪如何在MyEclipse10中配置自己的maven了&#xff0c;…...

怎么免费做自己的网站/合肥百度推广公司哪家好

先来介绍下 media&#xff0c;确切的说应该是 CSS media queries&#xff08;CSS 媒体查询&#xff09;&#xff0c;媒体查询包含了一个媒体类型和至少一个使用如宽度、高度和颜色等媒体属性来限制样式表范围的表达式。CSS3 加入的媒体查询使得无需修改内容便可以使样式应用于某…...

做网站推广和头条推广/app网络推广方案

最近在做项目中&#xff0c;用Maven管理项目间的依赖关系&#xff0c;遇到一个问题&#xff0c;快折腾死了&#xff0c;不过初步试出来一种解决方案。在此把问题及解决方案描述一下&#xff0c;以资共享。 问题描述&#xff1a;有两个项目A和B&#xff0c;Dynamic Web Projec…...

网站建设怎么付款/seo怎么优化排名

最近服务器经常出现打不开网站的现象&#xff0c;有时出现在上午&#xff0c;有时出现在中午&#xff0c;几乎天天都会出现一次&#xff0c;出现问题时&#xff0c;无论是回收程序池还是重启IIS或者关闭其它一些可能有影响的服务&#xff0c;都不能解决问题。网站打不开时&…...