STL-vector类的使用及其模拟实现

      在C++中,vector是标准模板库(STL)中的一种动态数组容器,它可以存储任意类型的元素,并且能够自动调整大小。vector提供了许多方便的成员函数,使得对数组的操作更加简单和高效。

vector的使用

vector的构造函数

vector迭代器

vector的成员函数

vector的模拟实现

    template<class T>
    class vector {
    public:
        typedef T* iterator;
        typedef const T* const_iterator;

        typedef ReverseIterator<iterator, T&, T*> reverse_iterator;
        typedef ReverseIterator<const_iterator, const T&, const T*> const_reverse_iterator;

        reverse_iterator rbegin()
        {
            return reverse_iterator(end());
        }

        reverse_iterator rend()
        {
            return reverse_iterator(begin());
        }
        vector()
            /*:_start(nullptr)
            ,_finish(nullptr)
            ,_end_of_stroage(nullptr)*/
        {}
        vector(initializer_list<T> il) {
            /*typename initializer_list<T>::iterator it = il.begin();
            while (it!=il.end()) {    
                push_back(*it);
                ++it;
            }*/
            for (auto& e : il) {
                push_back(e);
            }
        }
        vector(int n,const T& val=T())
            /*:_start(nullptr)
            , _finish(nullptr)
            , _end_of_stroage(nullptr)*/
        {
            reserve(n);
            for (int i = 0; i < n; i++) {
                push_back(val);
            }
        }
        //vector(const vector<T>& v) {
        //    //reserve(v.capacity());
        //    /*for (auto e : v) {
        //        push_back(e);
        //    }*/
        //    _start = new T[v.capacity()];
        //    //memcpy(_start, v._start, sizeof(T) * v.size());
        //    for (size_t i = 0; i < v.size(); i++) {
        //        _start[i] = v._start[i];
        //    }
        //    _finish = _start + v.size();
        //    _end_of_stroage = _start + v.capacity();
        //}
        //vector(const vector& v) {
        vector(const vector<T>& v) {
            vector<T> tmp(v.begin(), v.end());
            swap(tmp);
        }
        void swap(vector<T>& v) {
        //void swap(vector& v) {
            std::swap(_start, v._start);
            std::swap(_finish, v._finish);
            std::swap(_end_of_stroage, v._end_of_stroage);
        }
        //vector<vector<T>> 深层次的拷贝
        // v1=v2
        vector<T>& operator=(vector<T> v) {
        //vector& operator=(vector v) {
            swap(v);
            return *this;
        }
        // [first,last)
        template <class InputIterator>
        vector(InputIterator first, InputIterator last) {
            /*:_start(nullptr)
                , _finish(nullptr)
                , _end_of_stroage(nullptr)*/
            {
                while (first != last) {
                    push_back(*first);
                    ++first;
                }
            }
        }
        ~vector() {
            delete[] _start;
            _start = _finish = _end_of_stroage = nullptr;
        }
        iterator begin() {
            return _start;
        }
        iterator end() {
            return _finish;
        }
        const_iterator begin() const{
            return _start;
        }
        const_iterator end() const{
            return _finish;
        }
        void resize(size_t n,T val=T()) {
            if (n < capacity()) {
                //删除数据
                _finish = _start + n;
            }
            else {
                if (n > capacity()) {
                    reserve(n);
                }
                while (_finish != _start + n) {
                    *_finish = val;
                    ++_finish;
                }
            }
        }
        void reserve(size_t n) {
            if (n > capacity()) {
                size_t sz = size();
                T* tmp = new T[n];
                if (_start) {
                    //memcpy(tmp, _start, sizeof(T) * size());
                    for (size_t i = 0; i < sz; i++) {
                        tmp[i] = _start[i];
                    }
                    delete[] _start;
                }
                //_finish = tmp + size();//size()是原来空间的_finish-_start
                //_start = tmp;
                _start = tmp;
                _finish = _start + sz;
                _end_of_stroage = tmp + n;
            }
        }
        void push_back(const T& x) {
            if (_finish == _end_of_stroage) {
                reserve(capacity() ==0 ? 4:capacity()* 2);
            }
            *_finish = x;
            ++_finish;
        }
        void pop_back() {
            assert(!empty());
            --_finish;
        }
        //iterator insert(iterator pos, const T& val) {
        void insert(iterator pos, const T& val) {
            assert(pos >= _start);
            assert(pos <= _finish);

            if (_finish == _end_of_stroage) {
                size_t len = pos - _start;
                reserve(capacity() == 0 ? 4 : capacity() * 2);
                //扩容后更新pos,解决迭代器pos失效的问题
                pos = _start + len;
            }
            iterator end = _finish - 1;
            while (end >= pos) {
                *(end + 1) = *end;
                --end;
            }
            *pos = val;
            ++_finish;
            //return pos;
        }
        //void erase(iterator pos) {
        iterator erase(iterator pos) {
            assert(pos >= _start);
            assert(pos < _finish);

            iterator start = pos + 1;
            while (start != _finish) {
                *(start - 1) = *start;
                ++start;
            }
            --_finish;
            return pos;
        }
        size_t capacity() const {
            return _end_of_stroage - _start;
        }
        size_t size() const{
            return _finish - _start;
        }
        
        bool empty() {
            return _start == _finish;
        }
        T& operator[](size_t pos) {
            assert(pos < size());
            return _start[pos];
        }
        const T& operator[](size_t pos) const{
            assert(pos < size());
            return _start[pos];
        }
    private:
        iterator _start=nullptr;//指向第一个元素的迭代器
        iterator _finish= nullptr;//指向最后一个元素的下一个位置的迭代器
        iterator _end_of_stroage= nullptr;//指向分配的内存空间的末尾位置的迭代器
    };

}

vector的构造函数

        vector()
            /*:_start(nullptr)
            ,_finish(nullptr)
            ,_end_of_stroage(nullptr)*/
        {}
        vector(initializer_list<T> il) {
//C++11:没有实例化的类模板只要取内嵌类型就会报错,因为编译器分不清是类模板里面的静态变量(可以取)还是类型(实例化才能取)
//      说明类型时,前面要加typename
            /*typename initializer_list<T>::iterator it = il.begin();
            while (it!=il.end()) {    
                push_back(*it);
                ++it;
            }*/
            for (auto& e : il) {
                push_back(e);
            }
        }
        vector(int n,const T& val=T())
            /*:_start(nullptr)
            , _finish(nullptr)
            , _end_of_stroage(nullptr)*/
        {
            reserve(n);
            for (int i = 0; i < n; i++) {
                push_back(val);//尾插n个值为val的数据到容器当中
            }
        }

vector的拷贝构造

传统写法:

vector(const vector<T>& v) {
    //reserve(v.capacity());
    /*for (auto e : v) {
        push_back(e);
    }*/
    _start = new T[v.capacity()];
    //memcpy(_start, v._start, sizeof(T) * v.size());
    for (size_t i = 0; i < v.size(); i++) {
        _start[i] = v._start[i];
    }
    _finish = _start + v.size();
    _end_of_stroage = _start + v.capacity();
}

现代写法:
//vector(const vector& v) {
vector(const vector<T>& v) {
    vector<T> tmp(v.begin(), v.end());
    swap(tmp);
}
void swap(vector<T>& v) {
//void swap(vector& v) {
    std::swap(_start, v._start);
    std::swap(_finish, v._finish);
    std::swap(_end_of_stroage, v._end_of_stroage);
}

迭代器

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

赋值运算符重载

//vector<vector<T>> 深层次的拷贝
// v1=v2
vector<T>& operator=(vector<T> v) {
//vector& operator=(vector v) {
    swap(v);
    return *this;
}
// [first,last)
template <class InputIterator>
vector(InputIterator first, InputIterator last) {
    /*:_start(nullptr)
        , _finish(nullptr)
        , _end_of_stroage(nullptr)*/
    {
        while (first != last) {
            push_back(*first);
            ++first;
        }
    }
}

vector的析构函数

~vector() {
    delete[] _start;
    _start = _finish = _end_of_stroage = nullptr;
}

扩容

void resize(size_t n,T val=T()) {
    if (n < capacity()) {
        //删除数据
        _finish = _start + n;
    }
    else {
        if (n > capacity()) {
            reserve(n);
        }
        while (_finish != _start + n) {
            *_finish = val;
            ++_finish;
        }
    }
}
void reserve(size_t n) {
    if (n > capacity()) {
        size_t sz = size();
        T* tmp = new T[n];
        if (_start) {
            //memcpy(tmp, _start, sizeof(T) * size());
            for (size_t i = 0; i < sz; i++) {
                tmp[i] = _start[i];
            }
            delete[] _start;
        }
        //_finish = tmp + size();//size()是原来空间的_finish-_start
        //_start = tmp;
        _start = tmp;
        _finish = _start + sz;
        _end_of_stroage = tmp + n;
    }
}

尾插和尾删

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

void pop_back() {
    assert(!empty());
    --_finish;
}

插入和删除

void insert(iterator pos, const T& val) {
    assert(pos >= _start);
    assert(pos <= _finish);

    if (_finish == _end_of_stroage) {
        size_t len = pos - _start;
        reserve(capacity() == 0 ? 4 : capacity() * 2);
        //扩容后更新pos,解决迭代器pos失效的问题
        pos = _start + len;
    }
    iterator end = _finish - 1;
    while (end >= pos) {
        *(end + 1) = *end;
        --end;
    }
    *pos = val;
    ++_finish;
    //return pos;
}
//void erase(iterator pos) {
iterator erase(iterator pos) {
    assert(pos >= _start);
    assert(pos < _finish);

    iterator start = pos + 1;
    while (start != _finish) {
        *(start - 1) = *start;
        ++start;
    }
    --_finish;
    return pos;
}

获取容量大小

size_t capacity() const {
    return _end_of_stroage - _start;
}

获取元素个数

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

判断是否为空

bool empty() {
    return _start == _finish;
}

访问下标元素

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

重载运算符[ ]时需要重载一个适用于const容器的,因为const容器通过“下标+[ ]”获取到的数据只允许进行读操作,不能对数据进行修改

迭代器失效

       由于vector的元素是分配在连续的内存中,当进行insert和erase操作,都会使得插入点和删除点之后的元素挪位置,插入点和删除掉之后的迭代器全部失效。
       解决方法就是更新迭代器,对于删除,erase()返回的是删除元素的下一个位置,可以通过利用erase()方法可以返回下一个有效的 iterator来避免迭代器失效。insert同理,insert返回的是插入元素的迭代器的位置。

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

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

相关文章

机器学习-聚类算法

简介 本文主要内容&#xff1a; 聚类分析所涉及到的所有方面 和 经典划分聚类&#xff1a;K-means算法及其在python中的运用实例 补充介绍的内容包括&#xff1a;sklearn.datasets numpy.ndarray sklearn.cluster matplotlib.pyplot.scatter 聚类分析概述 聚类分析是无监督…

第23天:安全开发-PHP应用后台模块SessionCookieToken身份验证唯一性

第二十三天 一、PHP后台身份验证模块实现 二、Cookie&Session技术&差异 1.生成cookie的原理图过程&#xff1a;见上图 客户端向服务器发送HTTP请求。服务器检查请求头中是否包含cookie信息。如果请求头中包含cookie信息&#xff0c;则服务器使用该cookie来识别客户端…

ICLR 2024 | FTS-Diffusion: 用于合成具有不规则和尺度不变模式的金融时间序列的生成框架

ICLR 2024 | FTS-Diffusion: 用于合成具有不规则和尺度不变模式的金融时间序列的生成框架 原创 QuantML QuantML 2024-04-17 09:53 上海 Content 本文提出了一个名为FTS-Diffusion的新颖生成框架&#xff0c;用于模拟金融时间序列中的不规则和尺度不变模式。这些模式由于其独…

C++三大特性之一:继承

文章目录 前言一、继承方式二、继承类型继承中构造和析构的顺序继承中的内存分配多继承语法(非重点)继承中同名静态成员的处理继承一般在哪里用到进阶&#xff1a;菱形继承和虚拟继承 总结 前言 C三大特性&#xff1a;继承、多态和封装。继承是面向对象编程的一个核心概念&…

Elastic 网络爬虫:为你的网站添加搜索功能

作者&#xff1a;来自 Elastic Lionel Palacin 为了演示如何使用 Elastic 网络爬虫&#xff0c;我们将以一个具体的网站为例&#xff0c;讲解如何在该网站上添加搜索功能。我们将探讨发现网站的方法&#xff0c;并利用 Elastic 网络爬虫提供的功能&#xff0c;以最佳方式准备待…

HTML、CSS常用的vscode插件 +Css reset 和Normalize.css

个人主页&#xff1a;学习前端的小z 个人专栏&#xff1a;HTML5和CSS3悦读 本专栏旨在分享记录每日学习的前端知识和学习笔记的归纳总结&#xff0c;欢迎大家在评论区交流讨论&#xff01; 文章目录 ✍HTML、CSS常用的vscode插件&#x1f34e;1 HTML 标签同步重命名 – Auto Re…

【Java网络编程】网络编程中的基本概念及实现UDP、TCP客户端服务器程序

目录 一、什么是网络编程&#xff1f; 二、网络编程中的基本概念 1. 客户端和服务器 2. 请求和响应 三、Socket套接字 UDP数据报套接字编程 1. DatagramSocket 2. DatagramPacket 3. UDP回显客户端服务器程序 4. UDP字典客户端服务器程序 TCP流套接字编程 1. Serve…

SpringBoot 3.x + Swagger3 踩坑实录

问题描述 维护的SpringBoot版本是3.0版本&#xff0c;翻教程的时候发现很多SpringBoot2.x版本用的都是springfox&#xff0c;但问题是在SpringBoot3.x版本后&#xff0c;逐渐不支持springfox&#xff0c;强行启动会导致异常&#xff0c;现阶段使用的Springdoc进行替换。 参考…

Java多线程-API

常见API一览 Thread t1 new Thread(() -> {System.out.println("我是线程t1");System.out.println("Hello, World!"); }); t1.start(); // 获取线程名称 getName() // 线程名称默认是Thread-0, Thread-1, ... System.out.println(t1.getName());// 通过…

JVM类加载基本流程及双亲委派模型

1.JVM内存区域划分 一个运行起来的Java进程就是一个JVM虚拟机&#xff0c;这就需要从操作系统中申请一片内存区域。JVM申请到内存之后&#xff0c;会把这个内存划分为几个区域&#xff0c;每个区域都有各自的作用。 一般会把内存划分为四个区域&#xff1a;方法区(也称 "…

【网站项目】党员之家服务系统小程序

&#x1f64a;作者简介&#xff1a;拥有多年开发工作经验&#xff0c;分享技术代码帮助学生学习&#xff0c;独立完成自己的项目或者毕业设计。 代码可以私聊博主获取。&#x1f339;赠送计算机毕业设计600个选题excel文件&#xff0c;帮助大学选题。赠送开题报告模板&#xff…

【数字电路与系统】【北京航空航天大学】实验:时序逻辑设计——三色灯开关(二)、需求分析和系统设计

本次实验&#xff08;一&#xff09;见博客&#xff1a;【数字电路与系统】【北京航空航天大学】实验&#xff1a;时序逻辑设计——三色灯开关&#xff08;一&#xff09;、实验指导书 说明&#xff1a;本次实验的代码使用verilog编写&#xff0c;文章中为阅读方便&#xff0c…

指针的使用以及运算、二级指针、造成野指针的原因以及解决方法、指针和数组相互使用

第七章&#xff0c;指针的学习 目录 前言 一、指针的概念 二、指针的类型 三、野指针 四、指针的运算 五、指针和数组的关系以及使用 六、指针数组 七、二级指针 总结 前言 这章主要学习的是指针方面的知识&#xff0c;这节只是简单了解一下指针&#xff0c;并不会深…

uniapp H5项目 获取接口的二进制流转化成图片url(base64)

如果你使用的是uniapp, 并且你从接口获取下来的数据长这样&#xff1a; 想要把取到的数据展示成图片&#xff0c;那么你可以这样做&#xff1a; // 这是我们的项目封装的请求方法const res await this.$api.getKaptcha({originResponse: true, // 这样写是为了在request那边特…

路由器热备份

HSRP HSRP&#xff08;Hot Standby Routing Protocol&#xff09;热备份路由选择协议 HSRP是思科私有的协议&#xff0c;HSRP起到一个双网关热备份的一个目的&#xff0c;不考虑线路问题针对设备而言&#xff0c;一个设备挂了还有另外一台设备&#xff0c;所以双网关也叫双机…

stl_set

文章目录 set1.关联式容器2.键值对3. set3.1 set介绍3.2 set的使用3.2.1 pair3.2.2 find3.2.3 lower_bound 3.3 multiset3.3.1 multiset的介绍3.3.2 multiset的使用3.3.3 find3.3.4 equal_range3.3.5 erase set 1.关联式容器 在初阶阶段&#xff0c;我们已经接触过STL中的部分…

嵌入式物联网实战开发笔记-乐鑫ESP32芯片功能对比以及功能选型【doc.yotill.com】

乐鑫ESP32入门到精通项目开发参考百例下载&#xff1a; 链接&#xff1a;https://pan.baidu.com/s/1ATvRnAZvxkev-PJfd3EAPg?pwd4e33 提取码&#xff1a;4e33 2.1 初识 ESP32 ESP32-S3 是一款低功耗的 MCU 系统级芯片 (SoC)&#xff0c;支持 2.4 GHz Wi-Fi 和低功耗蓝牙 (…

强固型国产化工业电脑,在电子看板行业应用,机器视觉在汽车产线行业应用

电子看板行业应用 智能电子看板的核心是通过实现工厂的全面可视化、自动化管理&#xff0c;最终达到提高效率、降低成本及提高产品质量的目标。电子看板硬件主要有两部分组成&#xff1a;微型工业计算机&#xff0c;显示终端&#xff08;平板电视、LCD&#xff09; 方案需求 …

在Java中使用XxlCrawler时防止被反爬的几种方式

目录 前言 一、常见的反爬措施 1、User-Agent识别 2、Referer识别 3、频率限制 4、IP限制 二、XxlCrawer的应对之道 1、User-Agent应对 2、频率限制 3、IP限制 三、XxlCrawler执行解析 1、XxlCrawler对象 2、启动对象 3、信息爬取线程 总结 前言 众所周知&#x…

【c++】vector的使用

&#x1f525;个人主页&#xff1a;Quitecoder &#x1f525;专栏&#xff1a;c笔记仓 朋友们大家好&#xff0c;我们本篇来到一个新的容器&#xff0c;vector的讲解和使用 目录 1.vector简单介绍2.vector的使用2.1构造函数2.2遍历vector2.3对容量操作2.4vector的增删查改 1.v…