面试十五 容器

一、vector容器 

template<typename T>
class Allocator{
public:T* allocator(size_t size){// 负责内存开辟return (T*)malloc(sizeof(T) * size);}void deallocate(void * p){free(p);}void construct(T*p,const T&val){// 定位newnew (p) T(val);}void destroy(T*p){p->~T();}};template<typename T, typename Alloc = Allocator<T>>
class vector{
public:vector(int size=10){//  需要把内存开辟和对象构造分开处理//  _first = new T[size];_first= _allocator.allocator(size);_end = _first + size;_last =_first;}~vector(){//  delete[] _first;//  析构容器有效的元素,然后释放_first指针指向的堆内存for (T* p = _first; p != _last; ++p){_allocator.destroy(p); // 把_first指针指向的数组的有效元素进行析构操作}_allocator.deallocate(_first); // 释放堆上的数组内存_first=_last=_end= nullptr;}vector(const Vector<T>& src){int size = src._last-src._first;
//        _first =new T[size];_first = _allocator.allocator(size);int len=src._last-src._first;for(int i=0;i<len;i++){
//            _first[i]=src._first[i];_allocator.construct(_first + i, src._first[i]);}_last = _first + len;_end = _first + size;}vector<T>& operator=(const vector<T>&src){if(this==&src){return *this;}
//        delete[] _first;for (T* p = _first; p != _last; ++p){_allocator.destroy(p); // 把_first指针指向的数组的有效元素进行析构操作}_allocator.deallocate(_first);int size = src._end - src._first;int len = src._last - src._first;
//        _first = new T[size];_first=_allocator.allocate(size);for (int i=0; i<len; ++i) {
//            _first[i] = src._first[i];_allocator.construct(_first + i, src._first[i]);}_last = _first + len;_end = _first + size;return *this;}void push_back(const T &x) {if (full()) {resize();}
//        *_last ++ = x;_allocator.construct(_last, x);_last++;}void pop_back() {if (empty()) {return;}_allocator.destroy(_last);--_last;}T back() const {if (empty()) {}return *(_last-1);}bool full() {return _end == _last;}bool empty() {return _last == _first;}void resize() {int size=_end-_first;
//        T *tmp = new T[2*size];T* tmp = _allocator.allocator(2 * size);int len = _last-_first;
//        for(int i=0; i<len; ++i) {
//            tmp[i] = _first[i];
//        }
//        delete[] _first;for (int i = 0; i < size; ++i){//ptmp[i] = _first[i];_allocator.construct(tmp + i, _first[i]);}//delete[]_first;for (T* p = _first; p != _last; ++p){_allocator.destroy(p);}_allocator.deallocate(_first);_first = tmp;_end = _first + 2*size;_last = _first + len;}int size() const{return _last-_first;}T& operator[](int index){if(index<0 || index>=size()){throw "OutOfException";}return _first[index];}// 迭代器一般实现成容器的嵌套类型class iterator{public:iterator(T* ptr = nullptr):_ptr(ptr){}bool operator !=(const iterator &it) const{return _ptr !=it._ptr;}void operator++(){_ptr++;}T* operator*() {return *_ptr;}const T& operator*()const {return  *_ptr;}private:T* _ptr;};// 给容器提供begin() 和end()方法iterator begin(){return iterator(_first);}iterator end(){return iterator(_last);}// for each的底层也是iteratorprivate:T* _first;T* _last;T* _end;Alloc _allocator; // // 定义容器的空间配置器对象};int main() {Test t1;Test t2;vector<Test> vec;vec.push_back(t1);vec.push_back(t2);cout << "===========================" << endl;vec.pop_back();cout << "===========================" << endl;return 0;
}

二、迭代器失效

        迭代器失效是指:迭代器的底层其实就是容器的原生指针,插入元素可能导致容器内部的数据结构重新分配,从而使得原先的迭代器指向的位置不再有效;删除元素可能导致迭代器指向的位置被移动或删除,从而使得原先的迭代器不再指向期望的位置。也就是说原来的指针指向的内容被改变了,而不是现在内存中存的。

怎么判断迭代器失效没有:

        容器迭代器失效增加代码,它是一个结构体维护了一个链表。cur是指向某一个结构体的指针,又定义了一个指向下一个Iterator_Base节点的地址,还定义了一个头节点。记录了用户从中获取的哪一个元素的迭代器,记录在Iterator_Base链表中,哪一个迭代器增加或删除要让其失效并重新更新。 

        然后判断链表中的迭代器,看它是否在插入、删除点和_last之间,将会失效,失效的话将迭代器的容器对象赋值为nullptr,再进行 operator !=  、 operator++ 、 insert、erase进行操作时候,先判断迭代器是否失效。

    void verify(T* first,T* last){Iterator_Base *pre = &this->_head;Iterator_Base *it =this->_head._next;while(it!= nullptr){if(it->_cur->_ptr >first && it->_cur->_ptr <=last){it->_cur->_pVec = nullptr;pre->_next =it->_next;delete it;it=pre->_next;}else{pre=it;it=it->_next;}}}

 所有代码:

//
// Created by zhangchuang on 2024/4/22.
//#include <iostream>
using namespace std;
//#include <vector>template<typename T>
class Allocator{
public:T* allocator(size_t size){// 负责内存开辟return (T*)malloc(sizeof(T) * size);}void deallocate(void * p){free(p);}void construct(T*p,const T&val){// 定位newnew (p) T(val);}void destroy(T*p){p->~T();}};template<typename T, typename Alloc = Allocator<T>>
class vector{
public:vector(int size=10){//  需要把内存开辟和对象构造分开处理//  _first = new T[size];_first= _allocator.allocator(size);_end = _first + size;_last =_first;}~vector(){//  delete[] _first;//  析构容器有效的元素,然后释放_first指针指向的堆内存for (T* p = _first; p != _last; ++p){_allocator.destroy(p); // 把_first指针指向的数组的有效元素进行析构操作}_allocator.deallocate(_first); // 释放堆上的数组内存_first=_last=_end= nullptr;}vector(const vector<T>& src){int size = src._last-src._first;
//        _first =new T[size];_first = _allocator.allocator(size);int len=src._last-src._first;for(int i=0;i<len;i++){
//            _first[i]=src._first[i];_allocator.construct(_first + i, src._first[i]);}_last = _first + len;_end = _first + size;}vector<T>& operator=(const vector<T>&src){if(this==&src){return *this;}
//        delete[] _first;for (T* p = _first; p != _last; ++p){_allocator.destroy(p); // 把_first指针指向的数组的有效元素进行析构操作}_allocator.deallocate(_first);int size = src._end - src._first;int len = src._last - src._first;
//        _first = new T[size];_first=_allocator.allocate(size);for (int i=0; i<len; ++i) {
//            _first[i] = src._first[i];_allocator.construct(_first + i, src._first[i]);}_last = _first + len;_end = _first + size;return *this;}void push_back(const T &x) {if (full()) {resize();}
//        *_last ++ = x;_allocator.construct(_last, x);_last++;}void pop_back() {if (empty()) {return;}// 验证迭代器是否失效verify(_last-1, _last);// 如果是erase   验证verify(it._ptr, _last);// insert  验证verify(it._ptr, _last);_allocator.destroy(_last);--_last;}T back() const {if (empty()) {}return *(_last-1);}bool full() {return _end == _last;}bool empty() {return _last == _first;}void resize() {int size=_end-_first;
//        T *tmp = new T[2*size];T* tmp = _allocator.allocator(2 * size);int len = _last-_first;
//        for(int i=0; i<len; ++i) {
//            tmp[i] = _first[i];
//        }
//        delete[] _first;for (int i = 0; i < size; ++i){//ptmp[i] = _first[i];_allocator.construct(tmp + i, _first[i]);}//delete[]_first;for (T* p = _first; p != _last; ++p){_allocator.destroy(p);}_allocator.deallocate(_first);_first = tmp;_end = _first + 2*size;_last = _first + len;}int size() const{return _last-_first;}T& operator[](int index){if(index<0 || index>=size()){throw "OutOfException";}return _first[index];}// 迭代器一般实现成容器的嵌套类型class iterator{public:iterator(vector<T,Alloc>*pvec= nullptr,T* ptr = nullptr):_ptr(ptr),_pVec(pvec){Iterator_Base* itb = new Iterator_Base(this,_pVec->_head._next);_pVec->_head._next=itb;}bool operator !=(const iterator &it) const{// 检查迭代器的有效性if(_pVec == nullptr || _pVec!=it._pVec){throw "iterator incompatable!";return false;}return _ptr !=it._ptr;}void operator++(){// 检查迭代器的有效性,迭代器失效为空if(_pVec== nullptr){throw "iterator invalid";}_ptr++;}T* operator*() {return *_ptr;}const T& operator*()const {return  *_ptr;}private:T* _ptr;vector<T,Alloc> *_pVec;};// 给容器提供begin() 和end()方法iterator begin(){return iterator(_first);}iterator end(){return iterator(_last);}// 容器迭代器失效增加代码struct Iterator_Base{Iterator_Base(iterator *c = nullptr , Iterator_Base *n = nullptr):_cur(c),_next(n){}iterator *_cur;Iterator_Base *_next;};Iterator_Base _head;void verify(T* first,T* last){Iterator_Base *pre = &this->_head;Iterator_Base *it =this->_head._next;while(it!= nullptr){if(it->_cur->_ptr >first && it->_cur->_ptr <=last){it->_cur->_pVec = nullptr;pre->_next =it->_next;delete it;it=pre->_next;}else{pre=it;it=it->_next;}}}iterator insert(iterator it ,const T &val){// 1. 不考虑扩容// 2. 不考虑it._ptr的指针合法性verify(it._ptr -1 ,_last);T* p = _last;while(p>it._ptr){_allocator.construct(p,*(p-1));_allocator.destroy(p-1);p--;}_allocator.construct(p,val);_last++;return iterator(this,p);}iterator erase(iterator it ){// 1. 不考虑扩容// 2. 不考虑it._ptr的指针合法性verify(it._ptr -1 ,_last);T* p = _last;while(p<_last-1){_allocator.destroy(p);_allocator.construct(p,*(p+1));p++;}_allocator.destroy(p);_last--;return iterator(this,it._ptr);}// for each的底层也是iteratorprivate:T* _first;T* _last;T* _end;Alloc _allocator; // // 定义容器的空间配置器对象};
/*vector怎么*/#if 0
int main(){
//    std::vector<int>vec{1,2,3,4,5,6,8};/*迭代器失效问题1. 删除元素for(auto it =vec.begin();it!=vec.end();it++){if(*it%2==0){vec.erase(it);}}// 2.增加元素for(auto it =vec.begin();it!=vec.end();it++){if(*it%2==0){vec.insert(it,*it-1);}}*/// 2。 解决办法 -- 更新迭代器// 删除auto it =vec.begin();while(it!=vec.end()){if(*it%2==0){it=vec.erase(it);}else{++it;}}// 增加for(auto it =vec.begin();it!=vec.end();it++){if(*it%2==0){vec.insert(it,*it-1);++it;}}}
#endif

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/bicheng/3349.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

访问控制列表配置实验

ACL&#xff0c;全称 Access Control List&#xff08;访问控制列表&#xff09;&#xff0c;是一种实现访问控制的机制&#xff0c;用于规定哪些主体&#xff08;如用户、设备、IP地址、进程等&#xff09;可以对哪些资源&#xff08;如网络服务、文件、系统对象等&#xff09…

2024深圳杯C题的8页思路分析+所有代码可执行+参考文献+持续更新参考论文(已经更新了代码与图像)

比赛题目的完整版思路可执行代码数据参考论文都会在第一时间更新上传的&#xff0c;大家可以参考我往期的资料&#xff0c;所有的资料数据以及到最后更新的参考论文都是一次付费后续免费的。注意&#xff1a;&#xff08;建议先下单占坑&#xff0c;因为随着后续我们更新资料数…

C#面:简述 数组、链表、哈希、队列、栈数据结构特点,各自优点和缺点

C# 数组、链表、哈希、队列和栈是常见的数据结构&#xff0c;它们各自有不同的特点、优点和缺点。 数组&#xff1a; 特点&#xff1a;数组是一种线性数据结构&#xff0c;它由一组相同类型的元素组成&#xff0c;这些元素在内存中是连续存储的。优点&#xff1a;数组具有快速…

代码随想录-算法训练营day23【二叉树09:修剪二叉搜索树、将有序数组转换为二叉搜索树、把二叉搜索树转换为累加树】

代码随想录-035期-算法训练营【博客笔记汇总表】-CSDN博客 第六章 二叉树part09今日内容&#xff1a;● 669. 修剪二叉搜索树 ● 108.将有序数组转换为二叉搜索树 ● 538.把二叉搜索树转换为累加树 ● 总结篇 详细布置 669. 修剪二叉搜索树 这道题目比较难&#xff0c;比 添…

docker入门学习

一、docker概念 Docker 引擎是使用的是Linux内核特性的容器引擎。 二、docker的安装 1.docker&#xff0c;下载地址&#xff1a; 桌面版&#xff1a;Docker Desktop: The #1 Containerization Tool for Developers | Docker 服务器版&#xff1a;Install Docker Engine | D…

C++ 一种交换两个数的思路

在 Lua 或者 Python 中可以使用多值赋值语句来交换两个数。例如&#xff1a;a, b b, a。在 C 中有没有类似的操作&#xff1f; 先解析一下多值赋值的原理&#xff0c;a, b b, a 等价于 t1, t2 b, a a, b t1, t2可以看到多值赋值还是用到了中间变量&#xff0c;而且还是两…

# 从浅入深 学习 SpringCloud 微服务架构(六)Feign(3)

从浅入深 学习 SpringCloud 微服务架构&#xff08;六&#xff09;Feign&#xff08;3&#xff09; 一、组件的使用方式总结 1、注册中心 1&#xff09; Eureka 搭建注册中心 引入依赖 spring-cloud-starter-netflix-eureka-server。 配置 EurekaServer。 通过 EnableEure…

前端路由的实现原理

当谈到前端路由时&#xff0c;指的是在前端应用中管理页面导航和URL的机制。前端路由使得单页应用&#xff08;Single-Page Application&#xff0c;SPA&#xff09;能够在用户与应用交互时动态地加载不同的视图&#xff0c;而无需每次都重新加载整个页面。 在前端开发中&…

如何在阿里云快速配置自动定时重启ECS云服务器?

背景 无论是电子商务、在线教育、游戏&#xff0c;还是流媒体等业务&#xff0c;服务器的稳定运行都是至关重要的。然而&#xff0c;在实际运行中&#xff0c;我们可能会遇到这样一些场景&#xff1a; 系统更新&#xff1a;一些操作系统或者软件的更新可能需要重启服务器才能…

PCA9685芯片手册学习求教

概述 项目使用树莓派和PCA9685模块连接舵机进行控制&#xff0c;参照pca9685模块手册写了驱动代码&#xff0c;能按照预期进行控制舵机。 记录一下后续回看。 %PCA9685 此处提供此类的摘要% 初始化输入参数&#xff1a;芯片地址默认&#xff08;0x40),输出通道(ch),输出频率…

【QEMU系统分析之启动篇(十八)】

系列文章目录 第十八章 QEMU系统仿真的加速器上电后设置分析 文章目录 系列文章目录第十八章 QEMU系统仿真的加速器上电后设置分析 前言一、QEMU是什么&#xff1f;二、QEMU系统仿真的启动分析1.系统仿真的初始化代码2.主循环数据初始化3. accel_setup_post(current_machine) …

bit、进制、位、时钟(窗口)、OSI七层网络模型、协议、各种码

1.bit与进制 &#xff08;个人理解&#xff0c;具体电路是非常复杂的&#xff09; 物理层数据流&#xff0c;bit表示物理层数据传输单位&#xff0c; 一个电路当中&#xff0c;通过通断来表示数字1和0 两个电路要通讯&#xff0c;至少要两根线&#xff0c;一根作为电势参照…

Java中使用Graphics2D绘制字符串文本自动换行 算法

效果&#xff1a; 代码&#xff1a; /*** return void* Author xia* Description //TODO 写字换行算法* Date 18:08 2021/4/1* Param []**/private static void drawWordAndLineFeed(Graphics2D g2d, Font font, String words, int wordsX, int wordsY, int wordsWidth) {FontD…

东北大学工程训练CNC加工中心(坤图)

东北大学加工中心&#xff08;CNC&#xff09;采用的系统为FANUC系统。 要求学生自主设计图样&#xff0c;编写GCODE文件&#xff0c;操作电脑使机床按设计路径铣出图案。 本人设计的图样为坤坤图 图为用CAD设计绘制的图样。 计算坐标&#xff0c;设计铣刀轨迹&#xff0c;得…

Linux--基础IO(上)

目录 1. 文件的边角知识 1.1 文件是什么&#xff1f; 1.2 文件是怎么打开的&#xff1f; 1.3 进程与文件 进程与文件的关系 2. 重温c语言文件接口 2.1 打开文件的方式 2.2 读写文件接口的重温 2.2.1 写文件 2.2.2 读文件 3. 系统文件I/O 3.1 系统接口 3.2 系…

【深度学习-第5篇】使用Python快速实现CNN分类(模式识别)任务,含一维、二维、三维数据演示案例(使用pytorch框架)

在之前的文章中介绍了CNN的图解入门&#xff0c;CNN的MATLAB分类实现&#xff0c;CNN的MATLAB回归实现。 卷积神经网络(Convolutional Neural Networ&#xff0c;简称CNN)是一种广泛应用于图像识别领域的深度学习算法。它通过模拟人类视觉系统的层次结构&#xff0c;可以自动提…

半导体芯片相关知识

半导体工业构成 半导体工业是一个涉及多个领域和环节的复杂产业链&#xff0c;其构成包括但不限于以下几个方面&#xff1a; 芯片设计&#xff1a; 芯片设计是半导体工业的基础&#xff0c;包括集成电路&#xff08;IC&#xff09;设计、系统芯片设计、模拟电路设计等。芯片设…

nginx-1.24.0 安装教程

下载nginx安装包 mkdir -p /home/app cd /home/app wget http://nginx.org/download/nginx-1.24.0.tar.gz 解压缩 tar -zxf nginx-1.24.0.tar.gz 下载nginx二进制包编译所需的工具和依赖 yum install gcc-c pcre pcre-devel zlib zlib-devel openssl openssl-devel -y 编译…

Arduino平衡小车

一&#xff0c;TB6612FNG电机驱动芯片 TB6612FNG是东芝半导体公司生产的一款直流电机驱动器件&#xff0c;它具有大电流MOSFET-H桥结构&#xff0c;双通道电路输出&#xff0c;可同时驱动2个电机. 参数名称参数值电压范围2.7-5.5V最大输入电压15V输出电流1.2A(平均)/3.2A&…

Vitis HLS 学习笔记--HLS入门示例集合-目录

目录 1. 示例集合概述 2. Interface 接口 2.1 Aggregation_Disaggregation 聚合与解聚 2.1.1 aggregation_of_m_axi_ports 2.1.2 aggregation_of_nested_structs 2.1.3 aggregation_of_struct 2.1.4 auto_disaggregation_of_struct 2.1.5 disaggregation_of_axis_port …