c++:vector模拟实现

一、vector成员变量

 库里实现用的就是这三个成员变量,咱们实现跟库里一样,

namespace myvector {template<class T>class vector{public://vecttor的迭代器是原生指针typedef T* iterator;typedef const T* const_iterator;	private:iterator _start=nullptr;//数据块的开始--------------_beginiterator _finish=nullptr;//有效数据的尾-------------_enditerator _end_of_storage=nullptr;//存储容量的尾-----_capacity}

 这里把T*重命名为iterator,因为vector的迭代器就是原生指针,所以直接用就行。

二、默认成员函数

1.构造函数

        //我们在成员变量声明处给了缺省值,这里就可以不用初始化了vector(){}//T()是匿名对象,初始化n个valuevector(size_t n, const T& value = T()){resize(n, value);}/** 理论上讲,提供了vector(size_t n, const T& value = T())之后* vector(int n, const T& value = T())就不需要提供了,但是对于:* vector<int> v(10, 5);* 编译器在编译时,认为T已经被实例化为int,而10和5编译器会默认其为int类型* 就不会走vector(size_t n, const T& value = T())这个构造方法,* 最终选择的是:vector(InputIterator first, InputIterator last)* 因为编译器觉得区间构造两个参数类型一致,因此编译器就会将InputIterator实例化为int* 但是10和5根本不是一个区间,编译时就报错了* 故需要增加该构造方法*///初始化 n个valuevector(int n, const T& value = T()){resize(n, value);}// 若使用iterator做迭代器,会导致初始化的迭代器区间[first,last)只能是vector的迭代器// 重新声明迭代器,迭代器区间[first,last)可以是任意容器的迭代器//初始化一段空间template<class InputIterator>vector(InputIterator first, InputIterator last){while (first != last){push_back(*first);++first;}}

2.拷贝构造和赋值运算符重载

		//拷贝构造vector(const vector<T>&v){_start = new T[v.capacity()];//vector是深拷贝,但是vector空间上存一个开空间的自定义类型数组,例:string的数组//使用memcpy导致string对象的浅拷贝//memcpy(tmp, _start, sizeof(T) * size());for (size_t i = 0; i < v.size(); i++){//假设T是string类型,这里调用string的赋值运算符重载,是深拷贝_start[i]=v._start[i];}_finish = v.size() + _start;_end_of_storage = v.capacity() + _start;}vector<T>& operator=(vector<T> v){swap(v);return *this;}void swap(vector<T>& v){std::swap(v._start, _start);std::swap(v._finish, _finish);std::swap(v._end_of_storage, _end_of_storage);}

这里赋值运算符重载的形参是传值, 会调用拷贝构造出一个临时对象v,(深拷贝),然后用库里的swap把v的参数交换,交换完后待赋值运算符重载结束后会自动析构掉临时对象v。

  1. memcpy是内存的二进制格式拷贝,将一段内存空间中内容原封不动的拷贝到另外一段内存空间中
  2.  如果拷贝的是自定义类型的元素,memcpy既高效又不会出错,但如果拷贝的是自定义类型元素,并且自定义类型元素中涉及到资源管理时,就会出错,因为memcpy的拷贝实际是浅拷贝。

 

 结论:如果对象中涉及到资源管理时,千万不能使用memcpy进行对象之间的拷贝,因为memcpy是浅拷贝,否则可能会引起内存泄漏甚至程序崩溃。

3.迭代器

        //vecttor的迭代器是原生指针typedef T* iterator;typedef const T* const_iterator;iterator begin(){return _start;}iterator end(){return _finish;}const_iterator cbegin()const{return _start;}const_iterator cend()const{return _finish;}

 迭代器这里没什么大问题,直接用就行。

4.析构函数

		~vector(){if (_start){delete[] _start;_start = _finish = _end_of_storage;}}

 为空就没有可释放的资源。

、空间增长接口

        size_t capacity()const{return _end_of_storage - _start;}size_t size()const{return _finish - _start;}void reserve(size_t n){//只扩容,不缩容if (n > capacity()){size_t sz = size();T* tmp = new T[n];//如果_start为空,直接把tmp赋值给_start就行,不用释放旧空间if (_start){//vector是深拷贝,但是vector空间上存一个开空间的自定义类型数组,例:        //string的数组//使用memcpy导致string对象的浅拷贝//memcpy(tmp, _start, sizeof(T) * size());for (size_t i=0;i<size();i++){//假设T是string类型,这里调用string的赋值运算符重载,是深拷贝tmp[i] = _start[i];}delete[] _start;}_start = tmp;_finish = tmp + sz;_end_of_storage = tmp + n;}}void resize(size_t n, const T& value = T()){//三种情况//n<sizeif (n < size()){iterator pos = _start + n;while (pos != _finish){erase(pos);}}//n>容量,要扩容else if (n > size()){//n大于size但小于容量if (n > capacity()){reserve(n);}while (_finish != _start + n){push_back(value);}}}

这里只要注意临界条件就行了。

、增删接口

        void push_back(const T& value){满了,扩容//if (_finish == _end_of_storage)//{//	size_t newcapacity = capacity() < 4 ? 4 : capacity() * 2;//	reserve(newcapacity);//}//*_finish = value;//++_finish;insert(_finish, value);}void pop_back(){erase(_finish-1);}iterator insert(iterator pos, const T& x){assert(pos <= _finish);// 空间不够先进行增容if (_finish == _end_of_storage){//size_t size = size();size_t newCapacity = (0 == capacity()) ? 1 : capacity() * 2;reserve(newCapacity);// 如果发生了增容,需要重置pos,防止迭代器失效pos = _start + size();}iterator end = _finish - 1;while (end >= pos){*(end + 1) = *end;--end;}*pos = x;++_finish;return pos;}// 返回删除数据的下一个数据// 方便解决:一边遍历一边删除的迭代器失效问题iterator erase(iterator pos){// 挪动数据进行删除iterator begin = pos + 1;while (begin != _finish) {*(begin - 1) = *begin;++begin;}--_finish;return pos;}

 五、其他

        T& front(){return *_start;}T& back(){return *(_finish - 1);}T& operator[](size_t pos){//判断pos位置合法性assert(pos < size());return *(_start + pos);}const T& operator[](size_t pos)const{//判断pos位置合法性assert(pos < size());return *(_start + pos);}

总结

vector实现只要注意迭代器失效的问题和拷贝不能用memcpy这俩问题。

蟹蟹观看!点赞!关注!收藏!评论!一键三连!

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

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

相关文章

Microsoft.Extensions.Configuration 中检测到版本冲突

同一个项目用VS2019 可以正常打开编译运行 用VS2022打开编译报如下错误, 项目要求使用 .NET Core 2.2 版本 代码 说明 项目 文件 行 禁止显示状态 错误(活动) NU1107 Microsoft.Extensions.Configuration 中检测到版本冲突。直接安装/引用 Microsoft.Extensions.Configuratio…

【热门主题】000023 计算机视觉:算法与应用的深度探索

前言&#xff1a;哈喽&#xff0c;大家好&#xff0c;今天给大家分享一篇文章&#xff01;并提供具体代码帮助大家深入理解&#xff0c;彻底掌握&#xff01;创作不易&#xff0c;如果能帮助到大家或者给大家一些灵感和启发&#xff0c;欢迎收藏关注哦 &#x1f495; 目录 【热…

国产服务器平台离线部署k8s和kubesphere(含离线部署新方式)

"信创&#xff1a;鲲鹏麒麟&#xff0c;ARM64架构&#xff0c;实现K8s和Kubesphere的离线部署&#xff0c;全新方式助力企业高效运维。" 本文将深入探讨如何借助鲲鹏CPU(arm64)和操作系统Kylin V10 SP2/SP3,通过KubeKey制作KubeSphere与Kubernetes的离线安装包&#…

面试题整理 2

总结了本次面试遇到的值得整理记录的面试题。 目录 变量赋值判断 变量判断 Foreach使用 Mysql优化策略 合理的索引设计 查询优化 数据表结构设计 配置优化 合理使用事务 定期维护数据库 使用缓存 监控与性能分析 Redis主从复制 介绍 配置 示例 Redis 数据类型…

SOLID原则-单一职责原则

转载请注明出处:https://blog.csdn.net/dmk877/article/details/143447010 作为一名资深程序员越来越感觉到基础知识的重要性&#xff0c;比如设计原则、设计模式、算法等&#xff0c;这些知识的长期积累会让你突破瓶颈实现质的飞跃。鉴于此我决定写一系列与此相关的博客&…

「C/C++」C/C++ 之 指针详解

✨博客主页何曾参静谧的博客&#x1f4cc;文章专栏「C/C」C/C程序设计&#x1f4da;全部专栏「VS」Visual Studio「C/C」C/C程序设计「UG/NX」BlockUI集合「Win」Windows程序设计「DSA」数据结构与算法「UG/NX」NX二次开发「QT」QT5程序设计「File」数据文件格式「PK」Parasoli…

CSS--导航栏案例

利用CSS制作北大官网导航栏 详细代码如下&#xff1a; <!DOCTYPE html> <html><head><meta charset"utf-8"><title></title><style>*{margin: 0;padding: 0;}#menu{background-color: darkred;width: 100%;height: 50px…

【语义分割|代码解析】CMTFNet-2: CNN and Multiscale Transformer Fusion Network 用于遥感图像分割!

【语义分割|代码解析】CMTFNet-2: CNN and Multiscale Transformer Fusion Network 用于遥感图像分割&#xff01; 【语义分割|代码解析】CMTFNet-2: CNN and Multiscale Transformer Fusion Network 用于遥感图像分割&#xff01; 文章目录 【语义分割|代码解析】CMTFNet-2: …

基于 Python 的 Django 框架开发的电影推荐系统

项目简介&#xff1a;本项目是基于 Python 的 Django 框架开发的电影推荐系统&#xff0c;主要功能包括&#xff1a; 电影信息爬取&#xff1a;获取并更新电影数据。数据展示&#xff1a;提供电影数据的列表展示。推荐系统&#xff1a;基于协同过滤算法实现个性化推荐。用户系…

Spring Boot 集成 RocketMQ

在现代分布式系统中&#xff0c;消息队列扮演着至关重要的角色。它能够实现系统间的异步通信、解耦组件以及提高系统的可扩展性和可靠性。RocketMQ 作为一款高性能、分布式的消息中间件&#xff0c;被广泛应用于各种大规模系统中。而 Spring Boot 作为一种流行的 Java 开发框架…

Window系统性能调优

1. 系统设置优化 性能选项调整&#xff1a; 右键点击“此电脑” > “属性” > “高级系统设置” > “性能” > “设置”。在“视觉效果”选项卡中&#xff0c;选择“调整为最佳性能”以禁用不必要的动画和效果&#xff0c;或选择自定义禁用特定效果。 电源选项&…

高并发场景下的性能测试方法!

在现代互联网应用中&#xff0c;高并发场景下的性能测试显得尤为重要。无论是电商平台的秒杀活动&#xff0c;还是社交应用的突发流量&#xff0c;都需要确保系统能够在高并发情况下稳定运行。本文将详细介绍高并发场景下的性能测试方法&#xff0c;并提供具体的方案和实战演练…

苹果开发 IOS 证书生成步骤

前提条件 你手上有一台 Macbook你的苹果账号已被添加到开发人员中 证书创建步骤 打开 XCode 直接生成 p12证书生成后&#xff0c;就可在苹果开发者管理界面中看到你的证书记录登录苹果开发中心&#xff0c;创建 profiles 文件&#xff0c;并下载以上步骤即可&#xff0c;就这…

超萌!HTMLCSS:超萌卡通熊猫头

效果演示 创建了一个卡通风格的熊猫头 HTML <div class"box"><div class"head"><div class"head-copy"></div><div class"ears-left"></div><div class"ears-right"></di…

【Spark中创建RDD的两种方式】Spark中如何获取sc对象、以及创建RDD的两种方式

文章目录 一、Spark如何获取sc对象1、windons 本地模式获取sc对象2、linux 集群模式获取sc对象 二、创建RDD的两种方式1、并行化一个已存在的集合2、读取外部共享存储系统 一、Spark如何获取sc对象 不论是本地测试还是集群模式&#xff0c;都需要指定 JAVA_HOME 和 HADOOP_HOM…

RHCE第四天笔记

1.web服务器简介 &#xff08;1&#xff09;什么是www www是world wide web的缩写&#xff0c;也就是全球信息广播的意思。通常说的上网就是使用www来查询用户 所需要的信息。www可以结合文字、图形、影像以及声音等多媒体&#xff0c;并通过可以让鼠标单击超链接的方 式将信息…

springboot高校运动会管理系统-计算机毕业设计源码33814

摘要 本文旨在介绍基于Spring Boot框架和HTML技术开发的高校运动会管理系统。通过该系统&#xff0c;学校能够更高效地组织和管理校园内的各项体育赛事&#xff0c;提升运动会的组织效率和参与体验。系统整合了Spring Boot的强大功能和HTML的灵活性&#xff0c;为高校运动会管理…

Linux特种文件系统--tmpfs文件系统

tmpfs类似于RamDisk&#xff08;只能使用物理内存&#xff09;&#xff0c;使用虚拟内存&#xff08;简称VM&#xff09;子系统的页面存储文件。tmpfs完全依赖VM&#xff0c;遵循子系统的整体调度策略。说白了tmpfs跟普通进程差不多&#xff0c;使用的都是某种形式的虚拟内存&a…

森利威尔SL2516D 耐压60V内置5V功率MOS 支持PWM LED恒流驱动器芯片

一、基本特性 型号&#xff1a;SL2516D封装&#xff1a;ESOP8工作频率&#xff1a;140kHz驱动MOS管&#xff1a;内置 二、电气特性 输入电压范围&#xff1a;8V~100V&#xff08;注意&#xff0c;虽然问题中提到耐压60V&#xff0c;但根据官方信息&#xff0c;其实际耐压范围…

力扣287.寻找重复数

1.哈希表法 #include<stdio.h> #include<stdlib.h> int func(int *arr,int len) {int *hash(int *)malloc(sizeof(int)*len);for(int i0;i<len;i){if(hash[arr[i]]1){free(hash);return arr[i];}hash[arr[i]]1;}free(hash);return -1; }int main() {int arr[5]{…