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

手撕vector:从零实现一个C++动态数组

前言

在C++标准模板库(STL)中,vector是最常用的容器之一,它是一个动态数组,能够自动管理内存,支持随机访问。今天我们就来手把手实现一个简化版的vector,帮助初学者理解其内部原理。

基本结构

首先我们定义vector类的基本框架:

namespace yzq {template<class T>class vector {public:typedef T* iterator; // 定义迭代器typedef const T* const_iterator;  // 常量迭代器private:iterator _start = nullptr;iterator _finish = nullptr;iterator _end_of_storage = nullptr;};
}

这里我们使用三个指针来管理动态数组:

  • _start:指向数组的起始位置

  • _finish:指向最后一个元素的下一个位置

  • _end_of_storage:指向分配内存的末尾

迭代器

迭代器让我们能够像使用指针一样遍历容器:

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

内存管理

reserve函数

reserve函数用于预分配内存:

// 开内存
void reserve(size_t n) {if (n > capacity()) {size_t old_size = size();T* tmp = new T[n];for (size_t i = 0; i < old_size; i++) {tmp[i] = _start[i];}delete[] _start;_start = tmp;_finish = tmp + old_size;_end_of_storage = tmp + n;}
}

构造函数

我们的vector支持多种构造方式:

默认构造

// C++11支持的前置生成默认构造
vector() = default;

初始化构造

// 初始化构造
vector(size_t n, const T& value = T()) :_start(nullptr), _finish(nullptr), _end_of_storage(nullptr) {reserve(n);for (size_t i = 0; i < n; i++) {_start[i] = value;}_finish = _start + n;
}// 为整数类型提供特别的初始化构造,避免与通用区间构造混淆
vector(int n, int value = 0):_start(nullptr), _finish(nullptr), _end_of_storage(nullptr) {reserve(n);for (int i = 0; i < n; i++) {_start[i] = value;}_finish = _start + n;
}

区间构造

// 区间构造(针对vector类型)
vector(const_iterator first, const_iterator last):_start(nullptr), _finish(nullptr), _end_of_storage(nullptr) {size_t n = last - first;reserve(n);for (size_t i = 0; i < n; i++) {_start[i] = first[i];}_finish = _start + n;
}// 区间构造(通用版)
template<class InputIterator>
vector(InputIterator first, InputIterator last) :_start(nullptr), _finish(nullptr), _end_of_storage(nullptr) {while (first != last) {push_back(*first);first++;}
}

拷贝构造

// 拷贝构造(深拷贝)
vector(const vector<T>& v):_start(nullptr), _finish(nullptr), _end_of_storage(nullptr) {reserve(v.capacity());size_t i;for (i = 0; i < v.size(); i++) {push_back(v[i]);}
}

基本操作

容量相关

size_t size() const {return _finish - _start;
}size_t capacity() const {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];
}

修改操作

尾插和尾删
// 尾插
void push_back(const T& x) {// 满了先扩容if (_finish == _end_of_storage) {reserve(capacity() == 0 ? 4 : 2 * capacity()); // 2倍扩}*_finish = x;_finish++;
}// 尾删
void pop_back() {assert(size() > 0);_finish--;
}
插入和删除
// 插入
iterator insert(iterator pos, const T& x) {assert(pos >= _start && pos <= _finish);// 满了先扩容if (_finish == _end_of_storage) {size_t len = pos - _start; // 先计算原来的位置reserve(capacity() == 0 ? 4 : 2 * capacity()); // 2倍扩pos = _start + len; // 更新pos,避免迭代器失效}// 挪动数据iterator end = _finish;while (end > pos) {*(end) = *(end - 1);end--;}*pos = x;_finish++;return pos;
}// 指定位置删除
iterator erase(iterator pos) {assert(pos >= _start && pos < _finish);// 挪动数据iterator start = pos;while (start < _finish - 1) {*(start) = *(start + 1);start++;}_finish--;return pos;
}
调整大小
void resize(size_t n, const T& value = T()) {// 小于当前元素个数即为删除元素,大于则添加元素if (n < size()) {_finish = _start + n;}else {reserve(n);while (_finish < _start + n) {*_finish = value;_finish++;}}
}

其他操作

// 清除数据
void clear() {_finish = _start;
}// 交换
void swap(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=(vector<T> v) {swap(v);return *this;
}

工具函数

// 打印vector
void print_vector() const {auto it = begin();while (it != end()) {std::cout << *it << " ";it++;}std::cout << std::endl;
}

析构函数

// 析构
~vector() {delete[] _start;
}

测试代码

void TestVector() {yzq::vector<int> a;a.push_back(1);a.push_back(2);a.push_back(3);a.push_back(4);a.push_back(5);a.print_vector();for (int i = 0; i < a.size(); i++) {cout << a[i] << " ";}cout << endl;yzq::vector<int> b(a.begin()+1, a.end());  // 区间拷贝b.print_vector();yzq::vector<int> c(b); // 深度拷贝c.print_vector();a.resize(1);a.print_vector();a.resize(10, 2);a.print_vector();
}int main() {TestVector();
}
http://www.dtcms.com/a/557338.html

相关文章:

  • 2025年--Lc228-523. 连续的子数组和(带测试用例)-Java版
  • 统计学---2.描述性统计-参数估计
  • 辽宁城乡和住房建设部网站怎么做个网站
  • 太平洋建设集团网站网站登录失败怎么回事
  • 住宅小区物业管理系统网站建设开票 网站建设
  • 模块互相依赖问题解决的一个记录
  • 使用mujoco加载模型和控制、以及训练(一)
  • (125页PPT)麦肯锡业务流程规划方法论及流程规划案例(附下载方式)
  • AI学习研究——KIMI对佛教四圣谛深度研究
  • CSS padding(填充)
  • 通信原理(008)——模拟通信和数字通信
  • 山东城建设计院网站公司网站的重要性
  • C#快入教程:Linux安装.NET
  • 《深入浅出统计学》学习笔记(二)
  • 【内存管理】深入理解内存映射(Memory Mapping)与mmap:实现高效零拷贝的DMA缓冲区共享
  • Stm32江科大入门教程--各章节详细笔记---查阅传送门
  • 第六章langchain4j之Tools和prompt
  • 网站开发工作分解结构东营雪亮工程app下载二维码
  • re一下--day6--方法--经验贴
  • 【ubuntu】在Linux系统上安装Microsoft Edge浏览器
  • leetcode 3217. 从链表中移除在数组中存在的节点 中等
  • 滑县网站建设哪家便宜做竞价网站用什么系统好
  • 数学分析简明教程——1.4(未完)
  • element ui下拉框踩坑
  • 【仿RabbitMQ的发布订阅式消息队列】--- 服务端模块
  • C++ vector使用技巧:高效管理动态数据
  • (论文速读)CUT3R:具有持续状态的连续三维感知模型
  • 网站的flash怎么做的hyip网站开发
  • 上海网站建设润滋广州做鞋的网站
  • 互联网大厂Java面试:从Spring Boot到微服务的探索