C++ ——— 模拟实现 vector 类

ops/2025/1/23 4:30:48/

目录

vector%20%E7%B1%BB%E7%9A%84%E6%A1%86%E6%9E%B6-toc" name="tableOfContents" style="margin-left:0px">vector 类的框架

无参数的构造函数

析构函数

获取有效数据个数

获取容量

重载 [] 运算符

可读可写版本 

只可读版本

扩容

尾插

实现迭代器

可读可写版本 

只可读版本

自定义设置size长度和内容

在任意位置插入

删除任意位置的数据

赋值重载


vector%20%E7%B1%BB%E7%9A%84%E6%A1%86%E6%9E%B6">vector 类的框架

namespace rjj
{template<class T>class vector{public:    typedef T* iterator;private:iterator _start;iterator _finish;iterator _endofstorage;};
}

首先把要模拟实现的 vector 类用命名空间区分开来,以免和编译器自带的 vector 类冲突

vector 类要支持不同类型的实例化,所以使用模板来定义,这样在实例化的时候就能实例化不同的类型:vector<int>、vector<char>、vector<string> 等

_start 是指向空间起始位置的指针

_finish 是指向有效数据后一个位置的指针

_endofstorage 是指向开辟的动态空间末尾的指针


无参数的构造函数

vector():_stat(nullptr),_finish(nullptr),_endofstorage(nullptr)
{}

析构函数

~vector()
{delete[] _start;_start = _finish = _endofstorage = nullptr;
}

获取有效数据个数

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

获取容量

size_t capacity() const
{return _endofstorage - _start;
}

重载 [] 运算符

可读可写版本 

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

只可读版本

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

扩容

void reserve(size_t n)
{// 要保证扩容的大小大于当前容量if (n > capacity()){size_t sz = size();// 开辟新空间T* tmp = new T[n];// 拷贝并且释放旧空间if (_start){// 这样会出现浅拷贝问题// memcpy(tmp, _start, sizeof(T) * size());// 深拷贝for (int i = 0; i < sz; i++){tmp[i] = _start[i];}delete[] _start;}_start = tmp;_finish = _start + sz;_endofstorage = _start + n;}
}

尾插

void Push_back(const T& x)
{// 先判断是否需要扩容if (_finish == _endofstorage){reserve(capacity() == 0 ? 4 : capacity() * 2);}// 尾插数据*_finish = x;_finish++;
}

测试代码:


实现迭代器

可读可写版本 

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

直接使用原生指针即可实现

代码演示:

只可读版本

typedef const T* const_iterator;
const_iterator begin() const
{return _start;
}
const_iterator end() const
{return _finish;
}

自定义设置size长度和内容

void resize(size_t n, const T& val = T())
{if (n <= size()){_finish = _start + n;}else{// 先判断是否需要扩容reserve(n);while (_finish < _start + n){*_finish = val;_finish++;}}
}

当要设置的长度小于或等于 size() 时,也就是小于有效数据长度时,直接减小 _finish 的指向即可

当要设置的长度大于 size() 时,先判断是否需要扩容,在从 _finish 的位置依次往后赋值

测试代码:

小于时:

大于时:


在任意位置插入

void insert(iterator pos, const T& x)
{assert(pos >= _start);assert(pos <= _finish);// 先判断是否需要扩容if (_finish == _endofstorage){// 防止异地扩容后 pos 变成野指针,先记录长度size_t len = pos - _start;reserve(capacity() == 0 ? 4 : capacity() * 2);// 再重新赋值pos = _start + len;}// 指向最后一个数据的下一个位置iterator end = _finish;// 向后挪动while (end > pos){*end = *(end - 1);end--;}// 插入数据*pos = x;_finish++;
}

插入数据就会存在会扩容情况,如果扩容的话,pos 还是指向原来的空间,只要发生了扩容就会导致 pos 变成野指针,所以要使用 pos - _start 计算出长度先存储,不论是否扩容,再重新赋值 pos

测试代码:


删除任意位置的数据

iterator erase(iterator pos)
{assert(pos >= _start);assert(pos < _finish);// 指向 pos 位置的后一个位置iterator next = pos + 1;// 向前覆盖while(next < _finish){*(next - 1) = *next;next++;}_finish--;return pos;
}

测试代码:


赋值重载

void swap(vector<T>& v)
{std::swap(_start, v._start);std::swap(_finish, v._finish);std::swap(_endofstorage, v._endofstorage);
}
vector<T>& operator=(vector<T> tmp)
{swap(tmp);return *this;
}

http://www.ppmy.cn/ops/152370.html

相关文章

在Mac上安装Brew(Homebrew)——适用于Apple芯片(M1/M2系列)

在Mac上安装Brew&#xff08;Homebrew&#xff09;——适用于Apple芯片&#xff08;M1/M2系列&#xff09; Homebrew 是 macOS 上最受欢迎的包管理工具&#xff0c;它允许你轻松地安装和管理各种软件包和工具。对于使用 Apple Silicon 芯片&#xff08;如 M1 或 M2 芯片&#…

【HarmonyOS NAPI 深度探索6】使用 N-API 创建第一个 Hello World 原生模块

【HarmonyOS NAPI 深度探索6】使用 N-API 创建第一个 Hello World 原生模块 开发一个 N-API 模块听起来可能有点技术感十足&#xff0c;但实际上入门并不复杂。本文&#xff0c;我们来一步步实现一个简单的 Hello World 原生模块&#xff0c;感受一下 N-API 开发的魅力&#xf…

OpenHarmony OTA升级参考资料记录

OpenHarmony 作为一个开源分布式操作系统,通过其强大的 OTA(Over-The-Air)升级能力,为开发者和厂商提供了一套灵活而安全的系统升级方案。 OTA升级方式 根据升级包的应用方式,OpenHarmony 的 OTA 升级可以分为两种:本地升级和网络OTA升级。 本地升级 本地升级是将已制作…

【21】Word:德国旅游业务❗

目录 题目 NO1.2.3 NO4 NO5.6 NO7 NO8.9.10.11 题目 NO1.2.3 F12&#xff1a;另存为布局→页面设置→页边距&#xff1a;上下左右选中“德国主要城市”→开始→字体对话框→字体/字号→文本效果&#xff1a;段落对话框→对齐方式/字符间距/段落间距 NO4 布局→表对话框…

AI守护煤矿安全生产:基于视频智能的煤矿管理系统架构解析

前言 本文我将介绍我和我的团队自主研发设计的一款AI产品的成果展示——“基于视频AI识别技术的煤矿安全生产管理系统”。 这款产品是目前我在创业阶段和几位矿业大学的博士共同从架构设计、开发到交付的全过程中首次在博客频道发布, 我之前一直想写但没有机会来整理这套系统的…

查看电脑或笔记本CPU的核心数方法及CPU详细信息

一、通过任务管理器查看 1.打开任务管理器 可以按下“Ctrl Shift Esc”组合键&#xff0c;或者按下“Ctrl Alt Delete”组合键后选择“任务管理器”来打开。 2.查看CPU信息 在任务管理器界面中&#xff0c;点击“性能”标签页&#xff0c;找到CPU使用记录区域&#xff0c…

(k8s)k8s部署mysql与redis(无坑版)

0.准备工作 在开始之前&#xff0c;要确保我们的节点已经加入网络并且已经准备好&#xff0c;如果没有可以去看我前面发表的踩坑与解决的文章&#xff0c;希望能够帮到你。 1.k8s部署redis 1.1目标 由于我们的服务器资源较小&#xff0c;所以决定只部署一个redis副本&#x…

RV1126+FFMPEG推流项目(9)AI和AENC模块绑定,并且开启线程采集

前面两篇已经交代AI和AENC模块的配置&#xff0c;这篇就让这两个模块绑定起来&#xff0c;绑定的原因是&#xff0c;Aenc从Ai模块拿到采集的原始数据进行编码。 使用 RK_MPI_SYS_Bind 把 AI 节点和 AENC 进行绑定&#xff0c;其中 enModId 是模块 ID 号选择的是 RK_ID_AI、s32C…