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

手撕vector容器

一、vector容器的介绍

vector是表示可变大小数组的序列容器。就像数组一样,vector也采用的连续存储空间来存储元素,但是又不像数组,它的大小是可以动态改变的,而且它的大小会被容器自动处理。

总结:vector是一个动态数组,能高效的随机下标访问。
 

二、主要接口

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

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

容量空间接口说明
size获取数据个数
capacity获取容量大小
empty判断是否为空
resize(重点)改变vector的size
reserve (重点)改变vector的capacity

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

三、模拟实现

1.vector 的对象

iterator _start :                指向第一个元素的迭代器

iterator _finish:                  指向最后一个元素下一个位置的迭代器

iterator _endOfStorage :指向动态空间最后一个位置的迭代器

namespace N
{template<class T>class vector{public:typedef T* iterator;typedef const T* const_iterator;private:iterator _start = nullptr;iterator _finish = nullptr;iterator _endOfStorage = nullptr;};
}

模板命名T vector迭代器的本质是指针  

【C++11】关于成员对象给缺省,在构造函数调用初始化列表的时候,会选择用上缺省值

 2.迭代器成员函数begin()和end()

begin():返回指向容器的起始位置的迭代器(非const)

end():返回指向容器的最后位置的下一个位置迭代器(非const)

cbegin():返回指向容器的起始位置的常属性迭代器(const)

cend():返回指向容器的最后位置的下一个位置常属性迭代器(const)

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

区别:

非const的版本函数返回的迭代器可以用来访问,修改元素

而const版本只能用来访问元素,不准修改

3.容量空间

1)size():返回数据个数

        元素首位迭代器的相减返回个数  (前开后闭返回区间个数)

2)capacity()

        元素容量与头元素迭代器的相减

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

3)reserve(size_t  n) :改变vector的capacity

如果vector 的capacity大于n ,不进行操作

n>=capacity,扩容,拷贝,释放原空间

同时更新_start    _finish     _endofstorage

void reserve(size_t n)
{if (n <= capacity()){return;}T* tmp = new T[n];size_t sz = size();if (_start){for (size_t i = 0; i < sz; i++){tmp[i] = _start[i];}delete[]_start;}_start = tmp;_finish = _start + sz;_endOfStorage = _start+n;
}

4)resize :改变vector的size

n<size() 改变_finishi

n>=size() reserve空间,size后面的数依次赋值

void resize(size_t n, const T& value = T())
{if (n <= size()){_finish = _start + n;return;}reserve(n);while (_finish < n + _start){*_finish = value;++_finish;}
}

关于默认参数 :

匿名对象T()生命周期只有这一行

const修饰匿名对象 延长生命周期 value销毁时匿名对象才销毁

4.vector增删查改

1)push_back():尾插

检查容量,不够就reserve扩容  _finish位置插入数据 ++_finish

void push_back(const T& x)
{if (_finish == _endOfStorage)//扩容{reserve(capacity() == 0 ? 4 : capacity() * 2);}*_finish = x;++_finish;
}

2)pop_back():尾删

--_finish

void pop_back()
{_finish--;
}

3)insert(): pos位置之前插入val

检查pos合法

检查是否扩容,注意保存pos的位置,(求出pos-_start)

从最后一个数据往前挪动数据,插入val

更新_finish

iterator insert(iterator pos, const T& x)
{assert(pos>=_start);assert(pos <= _finish);int len = pos - _start;if (_finish == _endOfStorage){reserve(capacity() == 0 ? 4 : capacity() * 2);}pos = _start + len;//移动数据iterator end = _finish-1;while (end >= pos){*(end + 1) = *end;--end;}*pos = x;++_finish;return pos;
}

关于迭代器失效:

如果扩容后,原来的空间会被释放掉,那么pos会变成野指针,如果继续使用迭代器,会使用一块已经释放的空间,导致程序可能崩溃。

会引起其底层空间改变的操作,都有可能是迭代器失效,比如:resize、reserve、insert、assign、push_back等
 

4)earse():删除pos的值

检查pos的合法 _start<=pos<=_finish

从前往后挪数据

更新_finish

iterator erase(iterator pos)
{assert(pos >= _start);assert(pos <= _finish);iterator cur = pos+1;while (cur != _finish){*(cur - 1) = *cur;++cur;}--_finish;return pos;
}

涉及迭代器失效问题:

当earse最后一个位置时,迭代器失效,vs上认为使用earse后,不管删除哪个位置迭代器都失效

5)swap :交换俩个vector的数据空间

如果发生赋值,会极大降低效率,因此在vector容器的交换,交换各自的迭代器对象

void swap(vector<T>& v)
{::swap(_start, v._start);::swap(_finish , v._finish);::swap(_endOfStorage, v._endOfStorage);
}

6)operator [ ] :下标访问修改

返回指定空间的引用

T& operator[](size_t pos)
{assert(pos < size());return _start[pos];
}const T& operator[](size_t pos)const
{assert(pos < size());return _start[pos];
}

关于const版本和非const版本:
const只读不可改,非const版本可读可改

5.(constructor)构造函数声明

1)无参构造函数:

        不用写具体内容,因为在C++11支持成员变量给缺省,会自动进入初始化列表

2)vector(size_type n, const value_type& val = value_type()) N个value构造

        先开空间,附用reverse函数,尾插

vector(int n, const T& value = T())
{reserve(n);for (int i = 0; i < n; i++){push_back(value);}
}

3)vector(InputIterator first, InputIterator last):迭代器区间构造

定义迭代器模板,依次尾插

vector(InputIterator first, InputIterator last)
{while (first != last){push_back(*first);++first;}
}

4)vector (const vector &x):拷贝构造

开空间,尾插

vector(const vector<T>& v)
{reserve(v.capacity());for (auto e : v){push_back(e);}
}

5)operator =:赋值

拷贝构造临时空间,交换

vector<T>& operator= (vector<T> v)
{swap(v);return *this;
}

6)析构函数

释放空间

总结:

源代码:

STL/vector.h · L_may/C++Study - 码云 - 开源中国 (gitee.com)

本文模拟实现vector容器,在insert和erase中涉及迭代器失效的问题,要多加注意。

作者能力有限,希望对大家有所帮助。
 

相关文章:

手撕vector容器

一、vector容器的介绍 vector是表示可变大小数组的序列容器。就像数组一样&#xff0c;vector也采用的连续存储空间来存储元素&#xff0c;但是又不像数组&#xff0c;它的大小是可以动态改变的&#xff0c;而且它的大小会被容器自动处理。 总结&#xff1a;vector是一个动态…...

PyMuPDF`库实现PDF旋转功能

本文介绍了一个简单的Python应用程序&#xff0c;用于将PDF文件转换为旋转90度的PDF文件。主要用于csdn网站中导出的博客pdf是横向的&#xff0c;看起来不是很方便&#xff0c;才想到用python编制一个将pdf从横向转为纵向的功能。 功能 该PDF转换工具具有以下功能&#xff1a…...

微人事 登录问题完善

重启服务端的时候&#xff0c;发现前端页面会操作不了&#xff0c;这样后端session会失效&#xff0c;我们就需要让页面重新跳转到登录页 springsecurity配置类后端配置 前端拦截器进行拦截跳转...

【业务功能篇64】安装docker容器,在docker上安装mysql

docker教程&#xff1a; https://www.runoob.com/docker/docker-tutorial.html卸载docker 较旧的 Docker 版本称为 docker 或 docker-engine 。如果已安装这些程序&#xff0c;请卸载它们以及相关的依赖项。 yum remove docker docker-client docker-client-latest docker-co…...

MyBatis的基本概念和核心组件

MyBatis的基本概念 MyBatis 是一款优秀的持久层框架&#xff0c;它支持定制化 SQL、存储过程以及高级映射。MyBatis 避免了几乎所有的 JDBC 代码和手动设置参数以及获取结果集。MyBatis 可以使用简单的 XML 或注解来配置和映射原生信息&#xff0c;将接口和 Java 的 POJOs(Pla…...

sql update执行返回0,能否判断数据不存在

答案&#xff1a;不能。 update执行返回0的情况 1、没有找到需要更新的数据&#xff0c;就是这条记录不存在 例如&#xff1a;where后面的条件是id0&#xff0c;那这条记录肯定是不存在的&#xff0c;返回结果是0 2、更新时的数据和要更新的数据完全一致时 例如&#xff1a;更…...

数据分析 | 调用Optuna库实现基于TPE的贝叶斯优化 | 以随机森林回归为例

1. Optuna库的优势 对比bayes_opt和hyperoptOptuna不仅可以衔接到PyTorch等深度学习框架上&#xff0c;还可以与sklearn-optimize结合使用&#xff0c;这也是我最喜欢的地方&#xff0c;Optuna因此特性可以被使用于各种各样的优化场景。 2. 导入必要的库及加载数据 用的是sklea…...

stm32单片机开关输入控制蜂鸣器参考代码(附PROTEUS电路图)

说明&#xff1a;这个buzzer的额定电压需要改为3V&#xff0c;否则不会叫&#xff0c;源代码几乎是完全一样的 //gpio.c文件 /* USER CODE BEGIN Header */ /********************************************************************************* file gpio.c* brief Thi…...

打印X型的图案

int main() {int n0;int i0;int j0;scanf("%d",&n);for(i0;i<n;i){for(j0;j<n;j){if(ij){printf("*");}else if((ij)n-1){printf("*");}elseprintf(" ");}printf("\n");}return 0; }...

不含数字的webshell绕过

异或操作原理 1.首先我们得了解一下异或操作的原理 在php中&#xff0c;异或操作是两个二进制数相同时&#xff0c;异或(相同)为0&#xff0c;不同为1 举个例子 A的ASCII值是65&#xff0c;对应的二进制值是0100 0001 的ASCII值是96&#xff0c;对应的二进制值是 0110 000…...

Mac上传项目源代码到GitHub的修改更新

Mac上传项目源代码到GitHub的修改更新 最近在学习把代码上传到github&#xff0c;不得不说&#xff0c;真的还挺方便 这是一个关于怎样更新项目代码的教程。 首先&#xff0c;在本地终端命令行打开至项目文件下第一步&#xff1a;查看当前的git仓库状态&#xff0c;可以使用git…...

Android6:片段和导航

创建项目Secret Message strings.xml <resources><string name"app_name">Secret Message</string><string name"welcome_text">Welcome to the Secret Message app!Use this app to encrypt a secret message.Click on the Star…...

ClickHouse AST is too big 报错问题处理记录

ClickHouse AST is too big 报错问题处理记录 问题描述问题分析解决方案1、修改系统配置2、修改业务逻辑 问题描述 项目中统计报表的查询出现 AST is too big 问题&#xff0c;报错信息如下&#xff1a; 问题分析 报错信息显示 AST is too big。 AST 表示查询语法树中的最大…...

DPDK系列之二十七DIDO

一、DIDO介绍 随着计算机技术发展&#xff0c;特别是应用技术的快速发展。应用场景对计算机的处理速度几乎已经到了疯狂的地步。说句大白话&#xff0c;再快的CPU也嫌慢。没办法&#xff0c;CPU和IO等技术基本目前都处在了瓶颈之处&#xff0c;大幅度提高&#xff0c;短时间内…...

《游戏编程模式》学习笔记(七)状态模式 State Pattern

状态模式的定义 允许对象在当内部状态改变时改变其行为&#xff0c;就好像此对象改变了自己的类一样。 举个例子 在书的示例里要求你写一个人物控制器&#xff0c;实现跳跃功能 直觉上来说&#xff0c;我们代码会这么写&#xff1a; void Heroine::handleInput(Input input…...

博客系统之功能测试

博客系统共有&#xff1a;用户登录功能、发布博客功能、查看文章详情功能、查看文章列表功能、删除文章功能、退出功能 1.登录功能&#xff1a; 1.1测试对象&#xff1a;用户登录 1.2测试用例 方法&#xff1a;判定表 用例 编号 操作步骤预期结果实际结果截图1 1.用户名正确…...

CJS和 ES6 的语法区别

CommonJS 使用 module.exports 导出模块。ES6 使用 export 导出模块。 示例代码&#xff1a; CommonJS&#xff08;CJS&#xff09;模块的导出&#xff1a; // 导出模块 module.exports {foo: bar,baz: function() {return qux;} }; ES6 模块的导出&#xff1a; // 导出模…...

ArcGIS Pro如何制作不规则形状图例

在默认的情况下&#xff0c;ArcGIS Pro生成的图例是标准的点、直线和矩形的&#xff0c;对于湖泊等要素而言&#xff0c;这样的表示方式不够直观&#xff0c;我们可以将其优化一下&#xff0c;制作不规则的线和面来代替原有图例&#xff0c;这里为大家介绍一下制作方法&#xf…...

微软Win11 Dev预览版Build23526发布

近日&#xff0c;微软Win11 Dev预览版Build23526发布&#xff0c;修复了不少问题。牛比如斯Microsoft&#xff0c;也有这么多bug&#xff0c;所以你写再多bug也不作为奇啊。 主要更新问题 [开始菜单&#xff3d; 修复了在高对比度主题下&#xff0c;打开开始菜单中的“所有应…...

【NEW】视频云存储EasyCVR平台H.265转码配置增加分辨率设置

关于视频分析EasyCVR视频汇聚平台的转码功能&#xff0c;我们在此前的文章中也介绍过不少&#xff0c;感兴趣的用户可以翻阅往期的文章进行了解。 安防视频集中存储EasyCVR视频监控综合管理平台可以根据不同的场景需求&#xff0c;让平台在内网、专网、VPN、广域网、互联网等各…...

C++:std::is_convertible

C++标志库中提供is_convertible,可以测试一种类型是否可以转换为另一只类型: template <class From, class To> struct is_convertible; 使用举例: #include <iostream> #include <string>using namespace std;struct A { }; struct B : A { };int main…...

黑马Mybatis

Mybatis 表现层&#xff1a;页面展示 业务层&#xff1a;逻辑处理 持久层&#xff1a;持久数据化保存 在这里插入图片描述 Mybatis快速入门 ![在这里插入图片描述](https://i-blog.csdnimg.cn/direct/6501c2109c4442118ceb6014725e48e4.png //logback.xml <?xml ver…...

Redis相关知识总结(缓存雪崩,缓存穿透,缓存击穿,Redis实现分布式锁,如何保持数据库和缓存一致)

文章目录 1.什么是Redis&#xff1f;2.为什么要使用redis作为mysql的缓存&#xff1f;3.什么是缓存雪崩、缓存穿透、缓存击穿&#xff1f;3.1缓存雪崩3.1.1 大量缓存同时过期3.1.2 Redis宕机 3.2 缓存击穿3.3 缓存穿透3.4 总结 4. 数据库和缓存如何保持一致性5. Redis实现分布式…...

【SpringBoot】100、SpringBoot中使用自定义注解+AOP实现参数自动解密

在实际项目中,用户注册、登录、修改密码等操作,都涉及到参数传输安全问题。所以我们需要在前端对账户、密码等敏感信息加密传输,在后端接收到数据后能自动解密。 1、引入依赖 <dependency><groupId>org.springframework.boot</groupId><artifactId...

高频面试之3Zookeeper

高频面试之3Zookeeper 文章目录 高频面试之3Zookeeper3.1 常用命令3.2 选举机制3.3 Zookeeper符合法则中哪两个&#xff1f;3.4 Zookeeper脑裂3.5 Zookeeper用来干嘛了 3.1 常用命令 ls、get、create、delete、deleteall3.2 选举机制 半数机制&#xff08;过半机制&#xff0…...

页面渲染流程与性能优化

页面渲染流程与性能优化详解&#xff08;完整版&#xff09; 一、现代浏览器渲染流程&#xff08;详细说明&#xff09; 1. 构建DOM树 浏览器接收到HTML文档后&#xff0c;会逐步解析并构建DOM&#xff08;Document Object Model&#xff09;树。具体过程如下&#xff1a; (…...

MySQL 8.0 OCP 英文题库解析(十三)

Oracle 为庆祝 MySQL 30 周年&#xff0c;截止到 2025.07.31 之前。所有人均可以免费考取原价245美元的MySQL OCP 认证。 从今天开始&#xff0c;将英文题库免费公布出来&#xff0c;并进行解析&#xff0c;帮助大家在一个月之内轻松通过OCP认证。 本期公布试题111~120 试题1…...

面向无人机海岸带生态系统监测的语义分割基准数据集

描述&#xff1a;海岸带生态系统的监测是维护生态平衡和可持续发展的重要任务。语义分割技术在遥感影像中的应用为海岸带生态系统的精准监测提供了有效手段。然而&#xff0c;目前该领域仍面临一个挑战&#xff0c;即缺乏公开的专门面向海岸带生态系统的语义分割基准数据集。受…...

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

文章目录 前言一、感知机 (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 简单实现 (基于阈…...

虚拟电厂发展三大趋势:市场化、技术主导、车网互联

市场化&#xff1a;从政策驱动到多元盈利 政策全面赋能 2025年4月&#xff0c;国家发改委、能源局发布《关于加快推进虚拟电厂发展的指导意见》&#xff0c;首次明确虚拟电厂为“独立市场主体”&#xff0c;提出硬性目标&#xff1a;2027年全国调节能力≥2000万千瓦&#xff0…...