尝试实现带有迭代器的 vector

2023-11-01

两个注意点:

        1)底层内存分配采用 new 和 delete,非 stl 书中所示

        2)移动元素为集体后移,并非原书中拆解后移(原书移动方式原因未知)

#include <iostream>
#include <algorithm>
#include <string>

using namespace std;

template<class T>
class MyVector{

 protected:
  T* start;
  T* finish;
  T* end_of_storage;

  void fill_initialize(size_t n, const T& value){

    // 一旦使用 malloc,每次 ++ 都是一个字节,计算起来非常麻烦,使用new,每次++都是一个元素大小,更具有通用性
    // start = (T *)malloc(sizeof(T)*n);  // 申请n个T类型
    // finish = start + n * sizeof(T);

    start = new T[n];
    memset(start, value, n);
    finish = start + n;
    end_of_storage = finish;
  }

 public:
  MyVector():start(0), finish(0), end_of_storage(0){
  }

  MyVector(size_t n, const T& value){
    fill_initialize(n, value);
  }

  ~MyVector(){
    if (start != NULL){
      delete [] start;
    }
  }

  T& operator[](size_t pos){
    return *(start + pos);
  }

  T* begin(){
    return start;
  }

  T* end(){
    return finish;
  }

  size_t size(){
    return size_t(end() - begin()); // 指针是元素级别移动,而并非字节级别移动
  }

  size_t capacity(){
    return size_t(end_of_storage - begin());
  }

  T& front(){
    return *begin();
  }

  T& back(){
    return *(finish-1);
  }

  void push_back(const T& value){
    insert(end(), 1, value);
  }

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

  // 在指定位置插入 n 个元素
  void insert(T *position, size_t n, const T& x){

    if(n != 0){
      // 元素空间够用
      if(size_t(end_of_storage-finish) >= n){

        T *before = finish - 1;
        T *after = finish + n - 1;

        // 元素后移
        while (before >= position){
          *after = *before;
          after--;
          before--;
        }
        finish += n;  // 往后n个

        // 从插入点开始填入新值
        for (int i = 1; i <= n; ++i) {
          *position = x;
          position++;
        }

      }else{

        // 元素空间不够用
        // 两个长度选一: 原长度两倍,或者原长度+插入元素个数
        size_t len = max(capacity()*2, capacity()+n);
        T* new_start = new T[len];
        T* new_finish = new_start;

        // 将原有元素复制
        T* temp = start;
        while (temp != position){  // 复制插入之前的
          *new_finish = *temp;
          temp++;
          new_finish++;
        }

        // 插入的放入新空间
        for (int i = 1; i <= n; ++i) {
          *new_finish = x;
          new_finish++;
        }

        // 将后续的放入新空间
        while (temp != finish){
          *new_finish = *temp;
          temp++;
          new_finish++;
        }

        // 释放原空间
        delete [] start;
        start = new_start;
        finish = new_finish;
        end_of_storage = new_start + len;
      }
    }
  }

  // 清除某一段元素
  T* erase(T* op, T*ed){
    T *op_save = op;
    size_t len = ed - op;
    // 将后续元素进行拷贝
    T* temp = ed;
    while (temp != finish){
      *op = *temp;
      op++;
      temp++;
    }

    finish -= len;
    return op_save;
  }

  // 清除pos位置的元素
  T *erase(T *pos){
    return erase(pos, pos+1);
  }

  void resize(size_t n, const T& x){

    // 变大
    if(n > size()){
      insert(end(), n-size(), x);
    }else{

      // 变小
      erase(begin() + n, end());
    }
  }

  void resize(size_t n){
    resize(n, T());
  }

  void clear(){
    erase(begin(), end());
  }
};

template<class T>
void PrintVector(MyVector<T>& v){
  cout << "v.size(): " << v.size() << ", v.capacity():" << v.capacity() << endl;
  for (int i = 0; i < v.size(); ++i) {
    cout << v[i] << " ";
  }
  cout << endl;
}

void TestInt(){

  MyVector<int> v;

  v.push_back(1);
  v.push_back(2);
  v.push_back(3);
  v.push_back(4);
  v.push_back(5);

  PrintVector(v);

  v.pop_back();
  v.pop_back();

  PrintVector(v);

  v.insert(v.begin(), 6, 6);
  PrintVector(v);

  v.insert(v.begin() + 2, 3, 3);
  PrintVector(v);

  v.erase(v.begin()+1, v.end()-2);
  PrintVector(v);

  v.resize(5);
  PrintVector(v);

  v.resize(10, 0);
  PrintVector(v);
}

class Student{

 public:
    string name;
    int age;

    Student(string name, int age){
      this->name = name;
      this->age = age;
    }

    Student(){

    }
};

void PrintVectorClass(MyVector<Student> &v){
  cout << "v.size(): " << v.size() << ", v.capacity():" << v.capacity() << endl;
  for (int i = 0; i < v.size(); ++i) {
    cout << v[i].name << " " << v[i].age << endl;
  }
}

void TestClass(){

  MyVector<Student> v;
  Student s1("a", 1);
  Student s2("b", 2);
  Student s3("c", 3);
  Student s4("d", 4);
  Student s5("e", 5);
  Student s6("f", 6);

  v.push_back(s1);
  v.push_back(s2);
  v.push_back(s3);
  v.push_back(s4);
  v.push_back(s5);
  v.push_back(s6);

  PrintVectorClass(v);

  v.pop_back();
  v.pop_back();
  v.pop_back();
  PrintVectorClass(v);

  Student s7("g", 7);
  Student s8("h", 8);
  Student s9("i", 9);
  Student s10("j", 10);

  v.push_back(s7);
  v.insert(v.end()-2, 1, s8);
  v.insert(v.end()-3, 1, s9);
  v.insert(v.end()-4, 1, s10);

  PrintVectorClass(v);
  v.erase(v.begin()+3, v.begin()+5);
  PrintVectorClass(v);

  v.insert(v.begin(), 2, s4);
  PrintVectorClass(v);

  v.resize(5);
  PrintVectorClass(v);

  v.resize(10);
  PrintVectorClass(v);
}

int main(){
  TestClass();

  // TestInt();
}

        有任何疑惑,欢迎探讨

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

尝试实现带有迭代器的 vector 的相关文章

  • C# 和 Javascript SHA256 哈希的代码示例

    我有一个在服务器端运行的 C 算法 它对 Base64 编码的字符串进行哈希处理 byte salt Convert FromBase64String serverSalt Step 1 SHA256Managed sha256 new S
  • 如何使用GDB修改内存内容?

    我知道我们可以使用几个命令来访问和读取内存 例如 print p x 但是如何更改任何特定位置的内存内容 在 GDB 中调试时 最简单的是设置程序变量 参见GDB 分配 http sourceware org gdb current onl
  • pthread_cond_timedwait() 和 pthread_cond_broadcast() 解释

    因此 我在堆栈溢出和其他资源上进行了大量搜索 但我无法理解有关上述函数的一些内容 具体来说 1 当pthread cond timedwait 因为定时器值用完而返回时 它如何自动重新获取互斥锁 互斥锁可能被锁定在其他地方 例如 在生产者
  • WPF 中的调度程序和异步等待

    我正在尝试学习 WPF C 中的异步编程 但我陷入了异步编程和使用调度程序的困境 它们是不同的还是在相同的场景中使用 我愿意简短地回答这个问题 以免含糊不清 因为我知道我混淆了 WPF 中的概念和函数 但还不足以在功能上正确使用它 我在这里
  • Qt moc 在头文件中实现?

    是否可以告诉 Qt MOC 我想声明该类并在单个文件中实现它 而不是将它们拆分为 h 和 cpp 文件 如果要在 cpp 文件中声明并实现 QObject 子类 则必须手动包含 moc 文件 例如 文件main cpp struct Sub
  • 使用 System.Text.Json 即时格式化 JSON 流

    我有一个未缩进的 Json 字符串 例如 hash 123 id 456 我想缩进字符串并将其序列化为 JSON 文件 天真地 我可以使用缩进字符串Newtonsoft如下 using Newtonsoft Json Linq JToken
  • 如何将图像路径保存到Live Tile的WP8本地文件夹

    我正在更新我的 Windows Phone 应用程序以使用新的 WP8 文件存储 API 本地文件夹 而不是 WP7 API 隔离存储文件 旧的工作方法 这是我如何成功地将图像保存到 共享 ShellContent文件夹使用隔离存储文件方法
  • C# 中的递归自定义配置

    我正在尝试创建一个遵循以下递归结构的自定义配置部分
  • 在数据库中搜索时忽略空文本框

    此代码能够搜索数据并将其加载到DataGridView基于搜索表单文本框中提供的值 如果我将任何文本框留空 则不会有搜索结果 因为 SQL 查询是用 AND 组合的 如何在搜索 从 SQL 查询或 C 代码 时忽略空文本框 private
  • 如何衡量两个字符串之间的相似度? [关闭]

    Closed 这个问题需要多问focused help closed questions 目前不接受答案 给定两个字符串text1 and text2 public SOMEUSABLERETURNTYPE Compare string t
  • for循环中计数器变量的范围是多少?

    我在 Visual Studio 2008 中收到以下错误 Error 1 A local variable named i cannot be declared in this scope because it would give a
  • Qt表格小部件,删除行的按钮

    我有一个 QTableWidget 对于所有行 我将一列的 setCellWidget 设置为按钮 我想将此按钮连接到删除该行的函数 我尝试了这段代码 它不起作用 因为如果我只是单击按钮 我不会将当前行设置为按钮的行 ui gt table
  • 从库中捕获主线程 SynchronizationContext 或 Dispatcher

    我有一个 C 库 希望能够将工作发送 发布到 主 ui 线程 如果存在 该库可供以下人员使用 一个winforms应用程序 本机应用程序 带 UI 控制台应用程序 没有 UI 在库中 我想在初始化期间捕获一些东西 Synchronizati
  • 当操作繁忙时,表单不执行任何操作(冻结)

    我有一个使用 C 的 WinForms 应用程序 我尝试从文件中读取一些数据并将其插入数据表中 当此操作很忙时 我的表单冻结并且无法移动它 有谁知道我该如何解决这个问题 这可能是因为您在 UI 线程上执行了操作 将文件和数据库操作移至另一个
  • C++ 复制初始化和直接初始化,奇怪的情况

    在继续阅读本文之前 请阅读在 C 中 复制初始化和直接初始化之间有区别吗 https stackoverflow com questions 1051379 is there a difference in c between copy i
  • 如何使我的表单标题栏遵循 Windows 深色主题?

    我已经下载了Windows 10更新包括黑暗主题 文件资源管理器等都是深色主题 但是当我创建自己的 C 表单应用程序时 标题栏是亮白色的 如何使我自己的桌面应用程序遵循我在 Windows 中设置的深色主题 你需要调用DwmSetWindo
  • 在 Dynamics CRM 插件中访问电子邮件发件人地址

    我正在编写一个 Dynamics CRM 2011 插件 该插件挂钩到电子邮件实体的更新后事件 阶段 40 pipeline http msdn microsoft com en us library gg327941 aspx 并且在此阶
  • C - 直接从键盘缓冲区读取

    这是C语言中的一个问题 如何直接读取键盘缓冲区中的数据 我想直接访问数据并将其存储在变量中 变量应该是什么数据类型 我需要它用于我们研究所目前正在开发的操作系统 它被称为 ICS OS 我不太清楚具体细节 它在 x86 32 位机器上运行
  • 防止索引超出范围错误

    我想编写对某些条件的检查 而不必使用 try catch 并且我想避免出现 Index Out of Range 错误的可能性 if array Element 0 Object Length gt 0 array Element 1 Ob
  • 使用 libcurl 检查 SFTP 站点上是否存在文件

    我使用 C 和 libcurl 进行 SFTP FTPS 传输 在上传文件之前 我需要检查文件是否存在而不实际下载它 如果该文件不存在 我会遇到以下问题 set up curlhandle for the public private ke

随机推荐

  • Raspberry Pi 与Arduino SPI通信

    本教程介绍了使用SPI 串行外围设备接口总线 进行Raspberry Pi与Arduino通讯和控制的基本框架 SPI代表了一种非常完善的芯片间通信方法 该方法在两种设备的硬件中均实现 在这里 我们将详细探讨SPI 讨论硬件和软件注意事项
  • 波次

    播种式分拣是以汇总了多份订单的一个批次为单位进行分拣作业的 业内通常将这个作业的批次称为 波次 为了达到较高的工作效率 播种式分拣一般希望每个波次汇总较多的订单 但由于以下原因 每个波次汇总的订单绝不是越多越好 1完成订单的时间限制 通常情
  • JavaMail邮件发送不成功的那些坑人情况及分析说明

    前言 JavaMail的使用本身并不难 网上有不少案例 简单易懂 而且有详细的中文注解 但是由于JavaMail的机制设置不够完善 特别是异常出错时的参考信息太少 给初学者造成了不少麻烦 而我就是其中之一 在此 把我遇到过得那些坑总结出来
  • 图解人工智能知识架构(从知识角度告诉你人工智能到底学些啥)

    很多人都想学习人工智能 但是却不知道该学些啥 从宏观的视角搞清楚人工智能到底需要学习哪些领域的知识是至关重要的 这就好比要去逛一座大的商场 非常需要一份商场的楼层导览图 它能够告诉你各个楼层商户的分布 又好比去一个风景区游玩 非常需要一份景
  • VS2022安装easyx图形库教程

    下载easyx图形库 下载地址 EasyX Graphics Library for C 下载好后安装 点击安装 安装 前两项 easyx会自动识别VS版本 我们点击安装 安装好以后重启VS 测试一下 安装easyx推行库成功 问题 那么e
  • 5分钟带你快速了解微服务框架的前世今生

    目录 原始时代 青铜时代 黄金时代 铂金时代 钻石时代 星耀时代 王者时代 总结 原始时代 1969年11月 为了便于高校间共享资源 美国国防部高级研究计划管理局建立一个名为阿帕网络ARPAnet 起初只有四个节点 阿帕网起源 一年后阿帕网
  • 编程是一种“组合的艺术”

    编程是一种 组合的艺术 WPF实例分析 金旭亮 有这么一句名言 政治是一种妥协的艺术 这一规律同样适用于软件技术 就我个人的观点 软件开发在一定意义上是一种 组合的艺术 优秀的软件工程师类似于优秀的厨师 能将一些常见的原料变成一盘色香味俱全
  • git常用命令合集(建议收藏)

    1 git init将本文件夹初始化成一个本地git仓库 2 git clone xxx 将github上的远程克隆到本地 3 git add file1 file2 添加文件到暂存区 包括修改的文件 新增的文件 4 git add dir
  • 技术人修炼之道阅读笔记(四)低效的7个行为习惯

    技术人修炼之道阅读笔记 四 低效的7个行为习惯 如今 在许多企业为了提高团队的产出 996 非常盛行 但是效果却往往不令人满意 那么怎么来提高团队的工作效率呢 这里我们进行逆向思维 从造成低效的7个坏习惯说起 因为避免了低效的行为习惯 离高
  • 无限脉冲响应 (IIR) 滤波器

    1 基础知识 某正弦信号 频率为50Hz 这意味着 信号的模拟频率 f 50 Hz 注意它的单位是Hz 信号的表达式为 注意 模拟滤波器设计中用的频率是指模拟角频率 数字滤波器设计中用的频率是指归一化数字角频率 w 2 数字滤波器简介 数字
  • 程序员应对35岁中年危机的措施

    都说程序员是吃青春饭 我也问了一些身边周围的朋友 有已经在工作的 有正在出于中年危机的 有猎头公司工作的 觉得年龄问题对于程序员是一个致命的问题 正处在25左右的我们 应该如何应对10年后的中年危机呢 李开复给程序员的7建议 我觉得很对 特
  • 第二章正则表达式

    第二章 正则表达式 1 学习目标 掌握正则表达式的作用 掌握正则表达式的语法 了解常见的正则表达式 2 内容讲解 2 1 正则表达式的概念 正则表达式是对字符串操作的一种逻辑公式 就是用事先定义好的一些特定字符 及这些特定字符的组合 组成一
  • c中malloc申请堆空间使用及案例

    c中malloc申请堆空间 void test22 int pr pr int malloc sizeof int 128 申请128个int4字节空间 if pr NULL 判断是否申请成功 return memset pr 0 size
  • elasticsearch字符串包含查询

    query string 在查询的时候经常会遇到查询字符串是否包含的某个特定字符传的查询 可以使用query string实现 GET pv search query query string default field name quer
  • NodeJS-进程管理pm2/forever/nodemon/supervisor/ts-node-dev

    无论在开发阶段还是在上线阶段 对进程的管理是大大解决时间和成本的 pm2 node js server tools 1 安装 全局安装 yarn global add pm2 OR npm install pm2 g 局部安装 yarn a
  • springcloud报错:com.netflix.discovery.shared.transport.TransportException

    1 完整报错信息 com netflix discovery shared transport TransportException Cannot execute request on any known server 2 问题分析 1 服
  • 图片风格快速转换的简单web实现

    图片风格快速转换的简单web实现 图片风格转换 是指利用深度学习算法学习某种风格图片的特征 将其应用到另一张图片中 合成新风格的图片 目前技术较为成熟 github上有很多有趣的项目与应用 本项目核心代码基于fast neural styl
  • NCC常用操作自助工具

    selftool 介绍 NChome操作自助工具 对常用操作进行了集成 类图 工具使用 功能介绍 初始化配置 点击按钮可对nchome进行关联 重启服务 点击按钮一键重启服务 sysConfig 点击按钮一键打开home配置界面 clear
  • 云计算技术与应用赛项竞赛试题(样卷)

    选手须知 1 竞赛试题通过在线 云计算技术与应用 竞赛考试系统和书面文档共同发布 内容完全一致 如出现纸质任务书缺页 字迹不清 与考试系统中不一致等问题 请及时向裁判示意 并进行任务书的更换 2 参赛团队应在4小时内完成任务书规定内容 选手
  • 尝试实现带有迭代器的 vector

    两个注意点 1 底层内存分配采用 new 和 delete 非 stl 书中所示 2 移动元素为集体后移 并非原书中拆解后移 原书移动方式原因未知 include