【C++】vector的底层剖析以及模拟实现

一、vector的简单认识

        vector是表示可变大小数组的序列容器。 就像数组一样,vector也采用的连续存储空间来存储元素也就是意味着可以采用下标对vector的元素 进行访问,和数组一样高效。但是又不像数组,它的大小是可以动态改变的,而且它的大小会被容器自动处理。vector会分配一些额外的空间以适应可能的增长,因为存储空间比实际需要的存 储空间更大。不同的库采用不同的策略权衡空间的使用和重新分配。但是无论如何,重新分配都应该是对数增长的间隔大小,以至于在末尾插入一个元素的时候是在常数时间的复杂度完成的。与其它动态序列容器相比(deque, list and forward_list), vector在访问元素的时候更加高效,在末 尾添加和删除元素相对高效。对于其它不在末尾的删除和插入操作,效率更低。

二、vector的简单模拟实现

vector的底层我模仿库里面的实现方法,设计了三个指针:

class vector{public:typedef T* iterator;private:iterator _start; // 指向数据块的开始iterator _finish; // 指向有效数据的尾iterator _endOfStorage; // 指向存储容量的尾}

以及正向迭代器,不可修改迭代器,各种构造函数,析构函数, reserve(预开辟出空间,字符串还是原来的大小(一般不缩容))resize(将vector设定为指定大小,字符串占满所开辟的空间)push_back(尾插)pop_back(尾删)insert(在pos位置上插入x,并返回pos位置的地址)erase(删除pos位置上的元素,并返回该位置的地址)。

注意事项:迭代器失效

        以reserve为例,当reserve开辟新空间时会释放原来的旧空间,导致_start,_finish都不是原来的_start,_finish,如果此时贸然对_start,_finish进行运算,很可能会导致程序崩溃。我的做法是先记录下原来vector的长度,再用_start加上记录下的长度,就能得到正确的_finish,具体实现见下面代码。

完整代码

#pragma once
#include <iostream>
using namespace std;namespace sxb
{template<class T>class vector{public:typedef T* iterator;private:iterator _start; // 指向数据块的开始iterator _finish; // 指向有效数据的尾iterator _endOfStorage; // 指向存储容量的尾public:// Vector的迭代器是一个原生指针typedef const T* const_iterator;iterator begin(){return _start;}iterator end(){return _finish;}const_iterator cbegin() const{return _start;}const_iterator cend() const{return _finish;}// construct and destroyvector() {}//构造一个长度为n,值为value的vectorvector(int n, const T& value = T()){_start = new T[n+1];_finish = _start + n;_endOfStorage = _start + n;for (int i = 0; i < n; i++){*(_start + i) = value;}}template<class InputIterator>//利用一段迭代器构造vector(InputIterator first, InputIterator last){int len = 0;while (first != last)// 1 2 3 4 5{len++;first++;}len++;_start = new T[len+1];memcpy(_start, first, sizeof(T) * len);_finish = _start + len;_endOfStorage = _finish;}//利用已有的vector构造vector(const vector<T>& v){_start = new T[v.size() + 1];memcpy(_start, v.cbegin(), sizeof(T) * v.size());_finish = _start + v.size();_endOfStorage = _finish;}//赋值构造vector<T>& operator= (vector<T> v){vector(v);return *this;}~vector(){delete[] _start;_finish = nullptr;_endOfStorage = nullptr;}// capacitysize_t size() const{return _finish - _start;}size_t capacity() const{return _endOfStorage - _start;}void reserve(size_t n){if (n > capacity()){T* tmp = new T[n + 1];//迭代器失效处理int oldnum = _finish - _start;memcpy(tmp, _start, sizeof(T) * (_finish - _start));delete[] _start;_start = tmp;_finish = _start + oldnum;_endOfStorage = _start + n;}}void resize(size_t n, const T& value = T()){if (n > capacity()){int oldnum = _finish - _start;reserve(n);while ((_start + oldnum) != _endOfStorage){*(_start + oldnum) = value;oldnum++;}}else{_finish = _start + n;}}///access///T& operator[](size_t pos){return *(_start + pos);}const T& operator[](size_t pos)const{return *(_start + pos);}///modify/void push_back(const T& x){if (size() == capacity()){reserve(capacity() == 0 ? 4 : capacity() * 2);}_start[size()] = x;_finish++;}void pop_back(){_finish--;}void swap(vector<T>& v){std::swap(_start, v._start);std::swap(_finish, v._finish);std::swap(_endOfStorage, v._endOfStorage);}//迭代器失效iterator insert(iterator pos, const T& x){int len = 0;while (pos != _start){len++;pos--;}if (size() == capacity()){reserve(capacity() == 0 ? 4 : capacity() * 2);}iterator endfinish = _finish;while (endfinish > _start + len){*(endfinish) = *(endfinish - 1);endfinish--;}*endfinish = x;_finish++;return _start + len;}iterator erase(iterator pos){iterator pos2 = pos;while (pos != _finish - 1){*pos = *(pos + 1);pos++;}_finish--;return pos2;}};}

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

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

相关文章

高等数学相关知识点整理汇总

说明&#xff1a;由于工作原因可能更新不及时&#xff0c;内容逐步完善中… 一、空间解析几何与向量代数 二、多元函数的微分学 三、重积分 四、曲线积分与曲面积分 五、常微分方程 六、无穷级数

WPF中的ListBox样式(没被选择有点模糊,选中清晰,鼠标进入变大,移出变小)

<Style TargetType"ListBoxItem"><!-- 没有被选中就是有点模糊 --><Setter Property"Opacity" Value"0.5" /><Setter Property"MaxHeight" Value"75" /><Style.Triggers><!-- 触发器设…

基于HarmonyOS ArkTS中秋国庆祝福程序、以代码之名,写阖家团圆祝福

中秋、国庆双节将至&#xff0c;作为程序员&#xff0c;以代码之名&#xff0c;表达对于阖家团圆的祝福。本节将演示如何在基于HarmonyOS ArkUI的SwiperController、Image、Swiper等组件来实现节日祝福轮播程序。 规则要求具体要求如下&#xff1a; 1、根据主题&#xff0c;用…

Flutter 核心原理 - UI 框架(UI Framework)

Flutter 既能保证很高的开发效率&#xff0c;又能获得很好的性能。 这两年 Flutter 技术热度持续提高&#xff0c;整个 Flutter 生态和社区也发生了翻天覆地的变化。目前Flutter 稳定版发布到了3.0&#xff0c;现在已经支持移动端、Web端和PC端&#xff0c;通过Flutter 开发的…

sql注入重学

sql基本操作 基本查询语句 union (必须得是前面的列与后面的列相同才可以查询&#xff09; 看第二局uses表中的列有3列&#xff0c;而emails中的列只有两列&#xff0c;所有无法成功查询 这就相当于我们再加了一列 group by &#xff08;分组&#xff09; 相当于将其分为10列…

python-0004-django站点

站点 django自带站点用来操作增删改查 国际化&#xff08;汉化&#xff09; 项目setting.py # LANGUAGE_CODE en-us LANGUAGE_CODE zh-Hans # TIME_ZONE UTC TIME_ZONE Asia/Shanghai USE_I18N True USE_L10N True USE_TZ True创建模型 在子应用的models.py中创建&…

力扣大厂热门面试算法题 24-26

24. 两两交换链表中的节点&#xff0c;25. K 个一组翻转链表&#xff0c;26. 删除有序数组中的重复项&#xff0c;每题做详细思路梳理&#xff0c;配套Python&Java双语代码&#xff0c; 2024.03.14 可通过leetcode所有测试用例。 目录 24. 两两交换链表中的节点 解题思路…

硬盘新建分区时选4096扇区 是4K对齐吗?

环境&#xff1a; 固态硬盘 问题描述&#xff1a; 硬盘新建分区时或者格式化选4096扇区 是4K对齐吗 解决方案&#xff1a; 1.选择4096扇区大小&#xff0c;实际上是进行了4K对齐。在传统硬盘格式化时&#xff0c;通常会选择以4096字节&#xff08;4K&#xff09;为单位的扇…

html--钢琴

代码 <!DOCTYPE html> <html> <head> <meta http-equiv"Content-Type" content"text/html; charsetutf-8" /> <title>html钢琴</title> <script src"js/js.js"></script> <link href"…

CVE-2022-1310:RegExp[@@replace] missing write barrier lead a UAF

文章目录 环境搭建漏洞分析漏洞利用漏洞触发链RCE原语构造 总结参考 环境搭建 嗯&#xff0c;这里不知道是不是环境搭建的有问题&#xff0c;笔者最后成功的实现了任意地址读写&#xff0c;但是任意读写的存在限制&#xff0c;任意写 wasm 的 RWX 区域时会直接报错&#xff0c…

leetcode刷题日志-108/1382将有序数组转换为二叉搜索树/将二叉搜索树变平衡

由于这两道题思路极其类似&#xff0c;在此统一记录&#xff1a; 108题.将有序数组转换为平衡二叉搜索树 思路&#xff1a;给定的数组已经升序排列&#xff0c;而二叉搜索树中序遍历的结果就是升序&#xff0c;但是仅凭中序遍历不能确定一颗二叉树&#xff0c;但是题目只是说…

服务层组件

目录 连接层(Connection Pool) SQL接口(SQL Interface) 查询缓存(Caches&Buffers) Management Services&Utilities 查询分析器(Parser) 优化器(Optimizer)

深度学习框架大战:究竟选择TensorFlow还是PyTorch?

深度学习框架大战&#xff1a;究竟选择TensorFlow还是PyTorch&#xff1f; 一、TensorFlow概述二、PyTorch概述三、TensorFlow vs PyTorch四、选择指南五、未来展望六、总结 在当今这个由数据驱动的时代&#xff0c;人工智能编程已经成为了技术发展的核心。深度学习框架作为实现…

郭炜老师mooc第十一章数据分析和展示(numpy,pandas, matplotlib)

多维数组库numpy numpy创建数组的常用函数 # numpy数组import numpy as np #以后numpy简写为np print(np.array([1,2,3])) #>>[1 2 3] print(np.arange(1,9,2)) #>>[1 3 5 7] 不包括9 print(np.linspace(1,10,4)) #>>[ 1. 4. 7. 10.] # linespace(x,y,n)&…

【C++ 】stack 和 queue

1. 标准库中的stack stack 的介绍&#xff1a; 1. stack是一种容器适配器&#xff0c;专门用在具有后进先出操作的上下文环境中&#xff0c;其删除只能从容器的一端进行 元素的插入与提取操作 2. stack是作为容器适配器被实现的&#xff0c;容器适配器即是对特定类封装作为其…

Solidity 智能合约开发 - 基础:基础语法 基础数据类型、以及用法和示例

苏泽 大家好 这里是苏泽 一个钟爱区块链技术的后端开发者 本篇专栏 ←持续记录本人自学两年走过无数弯路的智能合约学习笔记和经验总结 如果喜欢拜托三连支持~ 本篇主要是做一个知识的整理和规划 作为一个类似文档的作用 更为简要和明了 具体的实现案例和用法 后续会陆续给出…

计算机硬件 8.3计算机的维护

第三节 计算机的维护 一、除尘 1.把主板上的CPU、风扇等部件拆卸下来&#xff0c;先用纸片盖住插槽&#xff0c;以免灰尘再次进入槽内。 2.主板印制板表面的灰尘宜用软毛刷轻轻地刷&#xff0c;以免破坏了电子电路。 3.风扇等部件灰尘比较顽固&#xff0c;需要把它们从转轴上…

配置管理可能存在的问题

一、配置管理 配置管理是一种系统性的方法&#xff0c;它结合了技术和管理手段&#xff0c;用于标识、记录、控制和报告系统或项目的配置项。这些配置项可能是硬件、软件、文档或其他任何与系统或项目相关的实体。典型配置项包括项目计划书、需求文档、设计文档、源代码、可执…

RUST 每日一省:rust logo收集

rust的logo集合&#xff0c;看看有没有你喜欢的&#xff0c;挑一个吧&#xff1b; GitHub - XuHugo/rust-logo: Collection of logo images for all rust languages 下边只是挑选了几个&#xff0c;更多的还是看github吧。

Apache Doris 2.1.0 版本发布:开箱盲测性能大幅优化,复杂查询性能提升 100%

亲爱的社区小伙伴们&#xff0c;我们很高兴地向大家宣布&#xff0c;在 3 月 8 日我们引来了 Apache Doris 2.1.0 版本的正式发布&#xff0c;欢迎大家下载使用。 在查询性能方面&#xff0c; 2.1 系列版本我们着重提升了开箱盲测性能&#xff0c;力争不做调优的情况下取得较好…