C++知识点 – vector模拟实现

文章目录

  • C++知识点 -- vector模拟实现
  • 一、vector
    • 1.整体结构
    • 2.构造及析构函数
    • 3.capacity和size
    • 4.[]重载
    • 5.reserve
    • 5.push_back和pop_back
    • 6.迭代器
    • 7.insert
    • 8.erase
    • 9.拷贝构造
    • 10.赋值重载
    • 11.resize
    • 12.front和back

一、vector

1.整体结构

代码如下:

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

2.构造及析构函数

代码如下:

     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);for (size_t i = 0; i < n; i++){push_back(val);}}~vector(){delete[] _strat;_start = _finish = _end_of_storage = nullptr;}

3.capacity和size

代码如下:

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

4.[]重载

代码如下:

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

5.reserve

代码如下:

     void reserve(size_t n){if (n > capacity()){size_t sz = size();//先保存size(),后面开新空间后size会更新T* tmp = new T[n];if (_start){memccpy(tmp, _start, sizeof(T) * sz);delete[] _start;}_start = tmp;_finish = _start + sz;_end_of_storage = _start + n;}}

这种写法是有问题的,因为vector中还有可能存自定义类型,如果使用memcpy来拷贝数据,就会发生浅拷贝。
直接赋值,自定义类型会调用赋值重载,就是深拷贝了。

     void reserve(size_t n){if (n > capacity()){size_t sz = size();//先保存size(),后面开新空间后size会更新T* tmp = new T[n];if (_start){//memccpy(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;}}

5.push_back和pop_back

代码如下:

     void push_back(const T& x){if (_finish == _end_of_storage){reserve(capacity() == 0 ? 4 : capacity() * 2);}*_finish = x;_finish++;}

如果形参的引用前不加const,那么以下的情况会报错:

由于string是单参形式的构造函数,会发生隐式类型转换,将常量字符串"xxxx"转为string类型,生成一个string的临时对象,而临时对象具有常性,传参时,形参的引用前不加const,就是权限放大,导致报错。

     void pop_back(){assert(_finish > _start);_finish--;}

6.迭代器

代码如下:

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

7.insert

代码如下:

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

这种写法会导致迭代器失效,具体情况如下:

 void TestVector2(){vector<int> v1;v1.push_back(1);v1.push_back(2);v1.push_back(3);v1.push_back(4);//v1.push_back(5);for (auto a : v1){cout << a << ' ';}cout << endl;auto pos = find(v1.begin(), v1.end(), 3);if (pos != v1.end()){v1.insert(pos, 25);}for (auto a : v1){cout << a << ' ';}cout << endl;}

在上面的测试代码中,如果只插入4个数据,此时容量是满的,在insert时就会扩容,开辟一块新空间,然后挪动数据,但是pos是一个迭代器,依然指向原空间的某个地址,此时原空间被释放了,pos就变成了野指针,这就叫做迭代器失效。
改进:在insert中扩容时,也要更新pos;

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

8.erase

代码如下:

     iterator erase(iterator pos){assert(pos >= _start);assert(pos <= _finish);iterator begin = pos + 1;while (begin < _finish){*(begin - 1) = *begin;++begin;}--_finish;return pos;//返回该位置的迭代器}

9.拷贝构造

代码如下:

     vector(vector<T>& v){_start = new T[v.szie()];memcpy(_strat, v._start, sizeof(T) * v.size());_finish = _start + v.size();_end_of_storage = _start + v.size();}

vector的拷贝构造不是使用memcpy来进行数据迁移,因为memcpy是浅拷贝,vector中有可能会存自定义类型,浅拷贝是不行的,因此,需要逐个数据进行迁移:

     vector(const vector<T>& v){_start = new T[v.szie()];for (size_t i = 0; i < v.size(); i++){_start[i] = v._start[i];}_finish = _start + v.size();_end_of_storage = _start + v.size();}

也可以复用push_back:

     vector(const vector<T>& v): _start(nullptr), _finish(nullptr), _end_of_storage(nullptr){reserve(v.size());for (auto e : v){push_back(e);}}

现代写法:

     //先写一个迭代器区间的构造函数类模板//方便使用其他容器的迭代器构造template<class InputIteratort>vector(InputIteratort first, InputIteratort last)//迭代器区间的构造函数: _start(nullptr), _finish(nullptr), _end_of_storage(nullptr){while (first != last){push_back(*first);first++;}}void swap(vector<T>& v){::swap(_start, v._start);::swap(_finish, v._finish);::swap(_end_of_storage, v._end_of_storage);}vector(const vector<T>& v)                                                           //: _start(nullptr), _finish(nullptr), _end_of_storage(nullptr){vector<T> tmp(v.begin(), v.end());swap(tmp);}

10.赋值重载

代码如下:

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

使用传值传参,v是形参的临时拷贝, 然后直接交换this和v,this就有了值,v出了作用域也会自动析构。

11.resize

代码如下:

     void resize(size_t n, const T& val = T())//T()是T类型的匿名对象{if (n > capacity()){reserve(n);}if (n > size()){while (_finish < _start + n){*_finish = val;_finish++;}}else{_finish = _start + n;}}

12.front和back

代码如下:

     T& front(){assert(size() > 0);return *_start;}T& bcak(){assert(size() > 0);return *(_finish - 1);}

C++知识点 -- vector模拟实现相关推荐

  1. Leetcode402 remove-k-digits贪心+vector模拟栈的思想

    题目 给定一个以字符串表示的非负整数 num,移除这个数中的 k 位数字,使得剩下的数字最小. 注意: num 的长度小于 10002 且 ≥ k. num 不会包含任何前导零. 示例 1 : 输入: ...

  2. 1390: 队列问题(1)(vector模拟)

    1390: 队列问题(1) Time Limit: 1 Sec Memory Limit: 128 MB Submit: 125 Solved: 50 [Submit][Status][Web Boa ...

  3. 1810: Huffuman树(vector模拟)

    zcmu: 1810: Huffuman树 Time Limit: 1 Sec Memory Limit: 128 MB Submit: 66 Solved: 47 [Submit][Status][ ...

  4. 约瑟夫环问题(vector模拟过程)

    1862: zbj的狼人杀 Time Limit: 1 Sec Memory Limit: 128 MB [Submit][Status][Web Board] Description 这天zbj和小 ...

  5. C++ [STL之vector模拟实现]

    本文已收录至<C++语言和高级数据结构>专栏! 作者:ARMCSKGT STL之vector模拟实现 前言 正文 空间结构 默认成员函数 构造函数 拷贝构造函数 赋值重载 析构函数 关于数 ...

  6. 1147 Heaps (30 分)【难度: 一般 / 知识点: 堆 模拟 】

    https://pintia.cn/problem-sets/994805342720868352/problems/994805342821531648 直接按照堆模拟即可,如果对于每一个根来说,它 ...

  7. C++ 【vector模拟实现】

    目录 1.vector注意事项 2.vector基本模拟实现 insert迭代器失效 erase迭代器失效场景 erase正确写法 总结:insert/erase不要直接访问pos,必须先更新pos位 ...

  8. 【C++】vector模拟实现及其应用

    文章目录 vector的介绍 vector的使用及其实现 vector的定义 vector iterator 的使用 vector空间增长问题 vector的增删查改 vector的介绍 vector ...

  9. 【C++】vector模拟实现

    文章目录 1.前提铺垫 2.构造和析构析构模拟 2.1构造相关 2.2 析构相关的 2.3 赋值运算符重载 2.4 接口测试 2.4.1 内置类型测试 2.4.2 自定义类型测试 3.迭代器相关接口模 ...

最新文章

  1. 写缓冲器 + 无效队列,优化MESI协议的性能
  2. 【bzoj3524】Couriers——主席树
  3. [Swift]LeetCode522. 最长特殊序列 II | Longest Uncommon Subsequence II
  4. 苹果ipa签名工具免越狱下载_苹果iphone免越狱使用iTunes 一键下载旧版本app
  5. map和hasmap的区别
  6. oracle中变量前加冒号_ORACLE 变量的定义和使用
  7. 常见MIME类型例表
  8. apache 版本_Apache官宣!ShardingSphere首个Apache版本发布
  9. sql语句:CASE WHEN END 的用法
  10. MindMaster Pro 7.2中文版 — 亿图思维导图
  11. WPF中直接打开网页方法总结
  12. 龙之谷手游微信连接授权服务器失败,龙之谷手游ios微信授权失败怎么办_龙之谷手游ios微信授权失败解决办法-66街机网...
  13. 损失 18 万,获刑 7 年,又又又是程序员删库!
  14. phoenix查不到数据_Phoenix查询测试经验总结
  15. Chrome开发者工具不完全指南:(三、性能篇)
  16. 轩小陌的Python笔记-Pandas时间序列与日期
  17. mysql自动备份快结束很卡_mysql备份慢以及自动重启问题——调整NUMA
  18. 盘点适合入门学习的C/C++开源项目
  19. android刷机刷系统
  20. 换三张麻将源代码php,理论先行:麻将换三张攻略大全

热门文章

  1. 列宁格勒—诺夫哥罗德战役
  2. UEFI工程模块--工程模块
  3. 快易需求文档编辑系统(二期)第一次迭代开发总结
  4. 基于uniapp+uview实现自定义导航栏
  5. 战士、魔法师与怪兽的战斗游戏
  6. 公众号内容拓展学习笔记(2021.5.12)
  7. linux的ps 分页显示,技术|5 个最酷的终端分页器
  8. Python + OpenCV 图片合成视频遇到的问题
  9. Optional详解
  10. C# 转账到个人支付宝