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://xiahunao.cn/news/2982380.html

如若内容造成侵权/违法违规/事实不符,请联系瞎胡闹网进行投诉反馈,一经查实,立即删除!

相关文章

YASKAWA安川机器人DX100轴板维修故障细节分享

随着科技的日新月异&#xff0c;机器人在工业生产中扮演的角色愈发重要。而作为机器人的“大脑”——电路板&#xff0c;其稳定运作对整个系统的可靠性至关重要。面对可能出现的YASKAWA安川机器人DX100轴板故障&#xff0c;如何快速、准确地诊断问题并予以解决呢&#xff1f;下…

nginx 卸载和安装超详细教程

一、前言 由于现在nginx有版本漏洞&#xff0c;所以很多安装过nginx的需要卸载重新安装&#xff0c;没安装过的&#xff0c;切记不要乱安装版本。 OK以上版本切记不能再用了&#xff01; 废话不多说&#xff0c;直接上干货。 二、卸载 1、停止Nginx进程 命令行停止&#xf…

《架构风清扬-Java面试系列第26讲》聊聊的LinkedBlockingQueue的特点及使用场景

LinkedBlockingQueue也是BlockingQueue接口的一个实现类之一 这个属于基础性问题&#xff0c;老规矩&#xff0c;我们将从使用场景和代码示例来进行讲解 来&#xff0c;思考片刻&#xff0c;给出你的答案 1&#xff0c;使用场景 实现&#xff1a;基于链表实现的阻塞队列&#…

路由器本地docker 下载node容器部署 thressjs文档

1. 每次启动本地文档太麻烦 &#xff0c;路由器刚好支持docker&#xff08;tp-link6088&#xff09; &#xff0c;部署上去自启动 2.

漫谈AI 时代的信息模型

模型化- 数字化转型的重要基石 在各行各业推行数字化转型过程中&#xff0c;构建信息化模型十分重要&#xff0c;它是数字化转型的基石。事实上&#xff0c;数字化转型的核心是“万物皆模型”&#xff0c;在工业领域&#xff0c;以德国为主导的工业4.0 发展进程中&#xff0c;…

七分钟“手撕”三大特性<多态>

目录 一、学习多态之前需要的知识储备 二、重写 1.什么是重写 2.重写可以干嘛 3.怎么书写重写 4.重载与重写的区别 三、向上转型 1.什么是向上转型&#xff1f; 2.向上转型的语法 3.向上转型的使用场景 四、多态是什么 六、多态实现 七、多态的好处 八、多态的缺…

机器学习/算法工程师面试题目与答案-数学基础部分

机器学习/算法工程师面试题目--数学基础部分 一、数学基础1、微积分SGD,Momentum,Adagard,Adam原理L1不可导的时候该怎么办sigmoid函数特性 2、统计学&#xff0c;概率论求 Max(a, b) 期望拿更长的玫瑰花的最好策略最大化工作天数的员工数切比雪夫不等式随机截成三段组成三角形…

[tkinter实现]汉字笔顺小软件

软件简介 本软件旨在帮助小学生通过互动式学习掌握汉字的基本笔画和笔顺。软件采用Tkinter库构建&#xff0c;提供了一个用户友好的图形界面&#xff0c;适合小学生使用。 主要功能&#xff1a; 汉字展示&#xff1a;软件能够展示单个汉字&#xff0c;并以动画形式演示其标准…

SWOT分析法:知彼知己的战略规划工具

文章目录 一、什么是SWOT分析法二、SWOT分析法如何产生的三、SWOT分析法适合哪些人四、SWOT分析法的应用场景五、SWOT分析法的优缺点六、SWOT分析实例 一、什么是SWOT分析法 SWOT分析法是一种用于评估组织、项目、个人或任何其他事物的战略规划工具。SWOT是Strengths&#xff…

每日OJ题_BFS解决拓扑排序③_力扣LCR 114. 火星词典

目录 力扣LCR 114. 火星词典 解析代码 力扣LCR 114. 火星词典 LCR 114. 火星词典 难度 困难 现有一种使用英语字母的外星文语言&#xff0c;这门语言的字母顺序与英语顺序不同。 给定一个字符串列表 words &#xff0c;作为这门语言的词典&#xff0c;words 中的字符串已…

光伏储能控制系统的功能策略

一、控制策略 1、功率控制策略 光伏阵列的输出功率受光照和温度影响&#xff0c;最大功率点是转换太阳能为电能的最高效点。MPPT控制器根据实时参数调整光伏阵列工作点&#xff0c;确保其始终处于最大功率输出状态&#xff0c;提高能量转换效率&#xff0c;增加发电量&#x…

基于51单片机智能鱼缸仿真LCD1602显示( proteus仿真+程序+设计报告+讲解视频)

基于51单片机智能鱼缸仿真LCD显示 1. 主要功能&#xff1a;2. 讲解视频&#xff1a;3. 仿真4. 程序代码5. 设计报告6. 设计资料内容清单&&下载链接资料下载链接&#xff1a; 基于51单片机智能鱼缸仿真LCD显示( proteus仿真程序设计报告讲解视频&#xff09; 仿真图prot…

免费开源!手机上有这一款软件就够了!

今天这款软件解决了你们最近常问我的资源问题&#xff0c;甚至解决的不是一种&#xff0c;而是好多种&#xff0c;所以这款软件我一定要分享给你&#xff0c;也建议需要这方面软件的小伙伴都去体验一下&#xff0c;说不定就爱上了呢。 01 - 简阅免费小说&#xff08;安卓&#…

低代码信创开发核心技术(四)动态元数据系统设计

一、概述 在当今快速发展的信息技术领域&#xff0c;动态元数据系统扮演着至关重要的角色。它不仅能够提供数据的描述信息&#xff0c;还能动态地适应业务需求的变化&#xff0c;从而提高系统的灵活性和可扩展性。构建一个动态元数据系统意味着我们可以在不重启系统的情况下&a…

CUDA的应用场景

CUDA的应用场景随着技术的发展不断扩展&#xff0c;其核心优势在于能够显著提高并行计算任务的处理速度&#xff0c;这对于任何需要处理大量数据和执行复杂计算的领域都是极其有价值的。CUDA开发的应用场景非常广泛&#xff0c;主要得益于其强大的并行计算能力&#xff0c;以下…

上网行为管理软件有哪些?三款常用上网行为管理软件评测

互联网的普及&#xff0c;企业和个人对于网络安全和信息保护的需求越来越高。为了确保网络环境的安全和稳定&#xff0c;上网行为管理软件应运而生。本文将对三款常用的上网行为管理软件进行评测&#xff0c;分别是域智盾、Splunk Enterprise Security和安企神。 1、域智盾 域…

冯喜运:4.24 周三黄金原油市场分析报告及操作策略

黄金消息面解析&#xff1a;周三(4月24日)黄金反弹后微幅回跌&#xff0c;金价在2325美元附近喘息。尽管美国国债收益率下降&#xff0c;美元走弱&#xff0c;金价未能维持涨势。标普全球PMI弱于预期&#xff0c;引发了对美联储可能降息的猜测。中东地缘紧张局势有所缓解&#…

dist包在windows的nginx下部署运行

nginx 附带下载包 我用夸克网盘分享了「nginx-1.18.0.zip」 链接&#xff1a;https://pan.quark.cn/s/e87bbf87a742 将dist放到html文件目录下 3.找到nginx的配置文件&#xff0c;conf 下&#xff0c;用编辑器打开 nginx.conf 编辑。 location ^~/api {rewrite ^/api/(.*)…

kubernetes中DaemonSet控制器

一、概念 使用DaemonSet控制器&#xff0c;相当于在节点上启动了一个守护进程。通过DaemonSet控制器可以确保在每个节点上运行Pod的一个副本。如果有心的node节点加入集群&#xff0c;则DaemonSet控制器会自动给新加入的节点增加一个Pod的副本&#xff1b;反之&#xff0c;当有…

企业工商信息查询API接口如何对接

企业工商信息查询API接口指的是输入公司名全称/注册号/社会统一信用代码的任意一种&#xff0c;获得企业工商注册登记中包含的各类重要信息&#xff0c;主要信息包括&#xff1a;注册号&#xff0c;注册资金&#xff0c;登记机关&#xff0c;注册地址&#xff0c;核准时间&…