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

从零开始的C++(十一)

vector的模拟实现:

1.构造函数:

vector(){}vector(int n, const T& value = T()){   reserve(n);for (int i = 0; i < n; i++){push_back(value);}}template<class InputIterator>vector(InputIterator first, InputIterator last){  auto it = first;while (it != last){push_back(*it);it++;}}void swap(iterator&v1,iterator&v2){iterator ret = v1;v1 = v2;v2 = ret;}vector(const vector<T>& v){vector<T>tmp(v.cbegin(), v.cend());swap(_start,tmp._start);swap(_finish, tmp._finish);swap(_endOfStorage, tmp._endOfStorage);}
       private:iterator _start = nullptr; // 指向数据块的开始iterator _finish = nullptr; // 指向有效数据的尾iterator _endOfStorage = nullptr; // 指向存储容量的尾

对象的成员使用了参数列表,防止随机值引发异常。同时,对于传同类型对象的构造函数,复用了传迭代器的构造函数创建临时对象,然后交换this所指对象和临时对象的成员的值,防止浅拷贝,并且利用临时变量销毁原本this对象的成员的内容。

2.赋值重载:

     vector<T>& operator= (vector<T> v){swap(_start, v._start);swap(_finish, v._finish);swap(_endOfStorage, v._endOfStorage);return *this;}

赋值重载的原理和拷贝构造类似,都是用临时对象交换赋值,此处不用创建临时对象的原因是在实参到形参的过程已经进行了拷贝构造,即此处形参就是临时对象,所以直接交换即可。

3.插入和删除

  void push_back(const T& x){if (size() == capacity()){reserve(size() * 2+1);}*(_finish) = x;_finish++;}void pop_back(){assert(size() > 0);_finish--;}void swap(vector<T>& v){swap(_start, v._start);swap(_finish, v._finish);swap(_endOfStorage, v._endOfStorage);}iterator insert(iterator pos, const T& x){   assert(pos-_start <= size());assert(pos - _start>= 0);if (size() == capacity()){  int sz = pos - _start;reserve(size() * 2+1);pos = _start + sz;}auto it = _finish-1;while (it >= pos){*(it + 1) = *it;it--;}*pos = x;_finish++;return pos;}iterator erase(iterator pos){   assert(pos-_start >= 0);assert(pos-_start < size());auto it = pos+1;while (it != _finish){*(it - 1) = *(it);it++;}--_finish;return pos;}

需要注意的是,insert和erase都可能会造成迭代器失效(即迭代器使用结果可能未定义或无法使用)。同时也需要注意判断插入、删除是否合理(是否越界等)。

4.扩容

void reserve(size_t n){if (n >capacity()){    int sz = size();iterator tmp = new T[n];if (_start!=nullptr){//值拷贝for (int i = 0; i < sz; i++){tmp[i] = _start[i];}}delete[]_start;//更新_start = tmp;_endOfStorage = _start + n;_finish = _start + sz;}}void resize(size_t n, const T& value = T()){if (n <=size()){_finish = _start + n;}else{reserve(n);while (size() < n){push_back(value);}}}

扩容应注意是深拷贝,因为成员可能是自定义类型,有自己的析构函数,如果是浅拷贝可能会出现二次delete的情况,也可能会出现析构导致内容变成随机值无法正常使用。

http://www.lryc.cn/news/199830.html

相关文章:

  • 驱动开发day2
  • 【CANoe】文件处理_hex文件读取解析
  • 人脸识别顶会论文及源码合集,含2023最新
  • 介绍drawio和图表使用场景
  • leetcode-1438: 绝对差不超过限制的最长连续子数组
  • 【数据结构初阶】九、排序的讲解和实现(直接插入 \ 希尔 \ 直接选择 \ 堆 \ 冒泡 -- C语言)
  • uview组件使用笔记
  • Linux1024一篇通俗易懂的liunx命令操作总结(第十课)
  • nuxt使用i18n进行中英文切换
  • 机器人制作开源方案 | 行星探测车实现WiFi视频遥控功能
  • Angular main 中的enableProdMode
  • 驱动day2:LED灯实现三盏灯的亮灭
  • Android 编译错误:module xxx1 missing dependencies:xxx2
  • 使用EasyExcel实现Excel导入导出
  • 京东手机销售数据:2023年9月京东手机行业TOP10品牌排行榜
  • 常量字符串
  • 【活体检测】“深度学习驱动的人脸反欺诈检测系统:性能提升与多模型支持“
  • Howler.js HTML5声音引擎
  • centos 7.9每天定期发送最新备份文件到另外一台服务器
  • 一文全面了解:一个神奇的 react-antd-admin 动态菜单
  • 二叉树,堆排序及TopK问题
  • iphone xr密码错误太多次 连接itunes
  • 设置RabbitMQ超时时间
  • QT计时器
  • 3-k8s-镜像仓库harbor搭建
  • 0基础学习PyFlink——模拟Hadoop流程
  • 【无人机】太阳能伪卫星VoLTE无人机设计(Matlab代码实现)
  • 2023.10.20 LED驱动
  • 【力扣刷题】回文链表、环形链表、合并两个有序链表
  • linux错误处理函数