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

C++ vector 核心功能解析与实现

目录

整体结构概述

赋值运算符重载

下标运算符重载

内存管理函数

元素访问函数

插入和删除操作

完整代码


在C++标准库中, vector  是一个非常常用的动态数组容器,它能够自动管理内存,并且提供了丰富的操作接口。本文将通过分析一段手写  vector  的核心代码,深入理解  vector  的底层实现原理。

整体结构概述

我们实现的  vector  类模板主要包含以下几个关键部分:

1. 数据成员:用于管理动态数组的内存和元素范围。

2. 赋值运算符重载:实现对象之间的赋值操作。

3. 下标运算符重载:支持通过  []  访问元素。

4. 内存管理函数: reserve  和  resize  用于控制动态数组的容量和大小。

5. 元素访问函数: front  和  back  用于获取容器的首元素和尾元素。

6. 插入和删除操作: push_back 、 pop_back 、 insert  和  erase  用于元素的增删。

cpptemplate <typename T>class vector {private:iterator _start; // 指向动态数组起始位置iterator _finish; // 指向最后一个有效元素的下一个位置iterator _end_of_storage; // 指向动态数组容量的末尾位置public:typesdef T* iterator;typesdef const T* const_iterator;// 以下是具体成员函数的实现};

赋值运算符重载

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

现代化写法

该函数实现了  vector  对象之间的赋值操作。通过调用  swap  函数交换当前对象和传入对象的内部数据( _start 、 _finish  和  _end_of_storage ),从而高效地完成赋值。 swap  函数的具体实现通常会交换两个对象的资源,而不是逐个复制元素,这样可以提高效率。

下标运算符重载

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

这两个函数实现了通过  []  操作符访问  vector  中的元素。第一个函数是非  const  版本,用于修改元素;第二个函数是  const  版本,用于在  const vector  对象上读取元素。通过  assert  确保访问的下标在有效范围内,防止越界访问。

内存管理函数

 reserve  函数

void reserve(size_t n){if (n > capacity()){size_t sz = size();t* tmp = new t[n];if (_start){//memcpy(_tmp,_start,sizeof(T)*sz);for (size_t i = 0;i < sz;i++){tmp[i] = _start[i];}delete[]_start;}_start = tmp;_finish = _start + sz;_end_of_storage = _start + n;}}

 reserve  函数用于确保  vector  的容量至少为  n 。如果  n  大于当前容量,会分配一块新的更大的内存,将原有的元素逐个复制到新内存中,然后释放旧内存,并更新  _start 、 _finish  和  _end_of_storage  指针。

resize  函数

cppvoid resize(size_t n, const T& val = T()) {if (n < size()) {_finish = _start + n;} else {reserve(n);while (_finish != _start + n) {*_finish = val;++_finish;}}}

 resize  函数用于改变  vector  的大小。如果  n  小于当前大小,会截断  vector ;如果  n  大于当前大小,会先调用  reserve  确保有足够的容量,然后将新增位置初始化为  val 。

元素访问函数

 front  函数


 

cppT& front() {return *_start;}const T& front() const {return *_start;}

 front  函数用于获取  vector  的首元素。非  const  版本允许修改首元素, const  版本则用于在  const vector  对象上获取首元素。

 back  函数

cppT& back() {return *(_finish - 1);}const T& back() const {return *(_finish - 1);}

 back  函数用于获取  vector  的尾元素。同样分为非  const  和  const  版本,分别用于修改和读取尾元素。

插入和删除操作

 push_back  函数

cppvoid push_back(const T& x) {insert(end(), x);}

 push_back  函数在  vector  的末尾插入一个元素,它通过调用  insert  函数实现。

 pop_back  函数

cppvoid pop_back() {erase(end() - 1);}

 pop_back  函数删除  vector  的尾元素,通过调用  erase  函数实现。

 erase  函数


 

cppiterator erase(iterator pos) {iterator begin = pos + 1;while (begin != _finish) {*(begin - 1) = *begin;++begin;}_finish--;return pos;}

 erase  函数删除指定位置的元素。通过将该位置之后的元素逐个向前移动,覆盖要删除的元素,然后更新  _finish  指针。

 insert  函数

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

 insert  函数在指定位置插入一个元素。如果当前容量已满,会先调用  reserve  扩大容量,然后将插入位置之后的元素逐个向后移动,腾出空间插入新元素,并更新  _finish  指针。

通过以上代码的实现,我们可以对  vector  的核心功能有一个更深入的理解,掌握动态数组的内存管理和元素操作的底层原理。在实际开发中,合理使用  vector  可以提高代码的效率和可读性。

完整代码

#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
using namespace std;
#include<assert.h>
namespace ldg
{template<class T>class vecctor{public://原生指针typedef T* iterator;typedef const T* const_iterator;size_t size() {return _finish - _start;}size_t capacity(){return _end_of_storage - _start;}bool empty()const {return _start == _finish;}iterator begin(){return _start;}iterator cend(){return _finish;}const_iterator cbegin()const{return _start;}const_iterator cend()const{return _finish;}//构造和销毁vector():_start(nullptr), _finish(nullptr), _end_of_storage(nullptr){}vector(size_t n,const T& val=T()):_start(nullptr), _finish(nullptr), _end_of_storage(nullptr){reserve(n);while (n--) push_back(val);}vector(int  n, const T& val = T()):_start(new T[n]), _finish(_start+n), _end_of_storage(_finish){for (int i = 0;i < n;i++)_start[i] = val;}template <class Inititerator>vector(Inititerator first, Inititerator last){while (first != last){push_back(*first);first++;}}//vector(const vector<T>& v)//	:_start(nullptr)//	, _finish(nullptr)//	, _end_of_storage(nullptr)//{//	_start = new T[v.capacity()];//	//memccpy(_start,v._start,sizeof(T)*v.size());//	for (size_t i = 0;i < size();i++)//	{//		_start[i] = v._start[i];//	}//	_finish = _start + v.size();//	_ens_of_storage = _start + v.capacity();//}vector(const vector<T>& v):_start(nullptr), _finish(nullptr), _end_of_storage(nullptr){reserve(v.capacity());for (auto e : v)push_back(e);}~vector(){if (_start) {delete[]_start;_start = _finish = _end_of_storage = nullptr;}}void swap(vector<T>& v){std::swap(_start, v._start);std::swap(_finish, v._finish);std::swap(_ens_of_storage, v._ens_of_storage);}vector<T>& operator=(vector<T>& v){swap(v);return *this;}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)*sz);for (size_t i = 0;i < sz;i++){tmp[i] = _start[i];}delete[]_start;}_start = tmp;_finish = _start + sz;_end_of_storage = _start + n;}}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;}}}T& front(){return *_start;}const T& front()const{return *_start;}T& back(){return *(finish-1);}const T& back()const{return *(finish - 1);}void push_back(const T& x){insert(end(), x);}void pop_back(){ease(end() - 1);}//pos位置插入x//删除pos位置,返回pos+1iterator erase(iterator pos){iterator begin = pos + 1;while (begin = _finish){*(begin - 1) = *begin;++begin;}_finish--;return pos;}iterator insert(iterator pos, const T& x){assert(pos <= finish);if (_finish == _end_of_storage){size_t len = pos-start;size_t newst = (capacity() == 0) ? 4 : capacity() * 2;reserve(newst);pos = _start + len;//防止迭代器失效}iterator end = _finish - 1;while (end >= pos){*(end + 1) = *end;end--;}*pos = x;finish--;return pos;//防止迭代器失效}private:iterator _start;iterator _finish;iterator _end_of_storage;};

相关文章:

  • TOGAF 敏捷冲刺:15 天 Scrum 冲刺实践
  • 新能源汽车零部件功率级测试方案搭建研究
  • STM32F103_HAL库+寄存器学习笔记19 - CAN发送中断+CAN接收中断+接收所有CAN报文+ringbuffer数据结构
  • 1.Vue3 - 创建Vue3工程
  • LeetCode 热题100题解(Java版本)
  • Anaconda Prompt 切换工作路径的方法
  • mac 本地 docker 部署 nacos
  • 多路由器通过RIP动态路由实现通讯(单臂路由)
  • 使用谷歌浏览器自带功能将网页转换为PDF文件
  • liunx中常用操作
  • 树莓派4b 连接USB无线网卡
  • Spark_SQL
  • 基于亚马逊云科技 Amazon Bedrock Tool Use 实现 Generative UI
  • 人工智能在运动医学中的最新应用方向探析
  • 安全协议分析概述
  • 空间注意力和通道注意力的区别
  • MYSQL之慢查询分析(Analysis of Slow MySQL Query)
  • Java实现希尔排序算法
  • 前端Javascript模块化 CommonJS与ES Module区别
  • TS中的泛型
  • 马上评|与其争论董宇辉该不该获奖,不如多关心文学
  • 中方决定对在涉港问题上表现恶劣的美国国会议员等实施制裁
  • 又有多地推进产科整合
  • 中国房地产报:以改促治实现楼市多难并解
  • 北理工:开除宫某党籍,免去行政职务,解除聘用关系
  • “75后”新任四川泸州市委副书记张伟,已任市政府党组书记