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返回的是插入元素的迭代器的位置。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

elementUi 日期选择器 组件禁止手输

添加:editable"false" <el-date-pickerv-model"formInline.EndTime"type"datetime"placeholder"选择结束时间"format"YYYY-MM-DD HH:mm:ss"value-format"YYYY-MM-DD HH:mm:ss":editable"false">&…

AI大模型量化格式介绍(GPTQ,GGML,GGUF,FP16/INT8/INT4)

在 HuggingFace 上下载模型时&#xff0c;经常会看到模型的名称会带有fp16、GPTQ&#xff0c;GGML等字样&#xff0c;对不熟悉模型量化的同学来说&#xff0c;这些字样可能会让人摸不着头脑&#xff0c;我开始也是一头雾水&#xff0c;后来通过查阅资料&#xff0c;总算有了一些…

通用变频器ACS800-04M-0320-3可议价

商业别名&#xff1a;ACS800-04M-0320-3 产品编号&#xff1a;68279429 ABB 型号名称&#xff1a;ACS800-04M-0320-3 目录说明&#xff1a;ACS800-04M-0320-3&#xff1b; ACS800-04M-0320-3 Pcont.max:250kW, Icont.max:521A 原产地&#xff1a;芬兰 (FI) 海关税则号&#xf…

# 从浅入深 学习 SpringCloud 微服务架构(二)模拟微服务环境(2)通过 RestTemplate 调用远程服务

从浅入深 学习 SpringCloud 微服务架构&#xff08;二&#xff09;模拟微服务环境&#xff08;2&#xff09;通过 RestTemplate 调用远程服务 段子手168 1、打开 idea 创建父工程 创建 artifactId 名为 spring_cloud_demo 的 maven 工程。 --> idea --> File -->…

client-go源码结构及客户端对象

一、基础知识介绍 1、GVR 和 GVK G Goup资源组&#xff0c;包含一组资源操作的集合VVersion资源版本&#xff0c;用于区分不同API的稳定程度及兼容性RResource资源信息&#xff0c;用于区分不同的资源APIKKind资源对象类型&#xff0c;每个资源对象都需要Kind来区分它自身代表…

老化测试电源作用及选购标准

老化测试电源作用及选购标准 为了保证电子产品的稳定性和可靠性&#xff0c;我们需要对产品进行老化测试。老化测试电源是一种专门用于测试电子元器件、电源模块等产品在长时间、持续负载工作状态下稳定性和可靠性的电源设备&#xff0c;也被称为“测试电源”、“老化电源”等。…

【Linux】进程的程序地址空间①

目录 前言&#xff1a; 1.什么是地址空间 区域划分 页表&#xff1a; 2.为什么要有地址空间 2.1 进程与内存解耦合 2.2安全 3.凭什么说进程具有独立性&#xff1a; 4.用地址空间解释一下申请内存 前言&#xff1a; 在C语言中&#xff0c;我们说我们将内存分为&#xff0c;栈区…

【目标跟踪】ByteTrack详解与代码细节

文章目录 一、前言二、代码详解2.1、新起航迹2.2、预测2.3、匹配2.4、结果发布2.5、总结 三、流程图四、部署 一、前言 论文地址&#xff1a;https://arxiv.org/pdf/2110.06864.pdf git地址&#xff1a;https://github.com/ifzhang/ByteTrack ByteTrack 在是在 2021 年 10 月…

同元软控专业模型库系列——热流篇

一、引言 传热与流动是自然界与科学技术领域最普遍的物理现象。聚焦工业领域&#xff0c;传热、流体流动和燃烧问题是热工、核能、动力机械等行业所需研究解决的主要问题。复杂热流系统往往具有高复杂性、高成本性和高可靠性的特点&#xff0c;传统研制模式已逐渐无法满足现有…

【UE5.1 C++】提升编译速度

步骤 1. 在“C:\Users\用户\AppData\Roaming\Unreal Engine\UnrealBuildTool”目录下找到“BuildConfiguration.xml”文件 打开“BuildConfiguration.xml”&#xff0c;添加如下部分内容 <?xml version"1.0" encoding"utf-8" ?> <Configuratio…

干货:40个数据统计和分析的术语,让你的可视化大屏有理有据

1. 总体&#xff08;Population&#xff09;&#xff1a;指研究对象的全体&#xff0c;即研究问题所涉及的所有个体或事物的集合。 2. 样本&#xff08;Sample&#xff09;&#xff1a;从总体中选取的一部分个体或事物&#xff0c;用于代表总体进行研究。 3. 参数&#xff08…

MySQl-8.3.0版本安装下载教程(超详细保姆级教程)

第一步&#xff0c;去百度找到MySQl官网 第二步,找到DOWNLOAD&#xff08;下载&#xff09; 第三步 第四步 第五步 第六步.选择倒数第2个 第七步 第八步然后根据步骤安装就好了

我最重要的三个女人都生病了,两个已经住院了

往年的金三银四&#xff0c;大部分时间我都在面试&#xff0c;今年的金三银四&#xff0c;却一直往医院跑了。 我最重要的三个女人全生病了&#xff0c;病毒感染&#xff0c;20号我妈办理了住院&#xff0c;21 号我闺女小白牙办理了住院&#xff0c;她俩还不是同一家医院媳妇儿…

2024Xtu程设第一次练习题解

程设练习题谢大会专门查重 1.1531奇怪的数字 题目让我们从小到大输出1e6以内所有的答案&#xff0c;其实也没什么好的思路 就是将一个数n的所有位都拆出来&#xff0c;遍历这些位&#xff08;每次取一个x&#xff09;&#xff0c;然后通过作除法&#xff08;y n / x&#xf…

研究助理(博士后),院所两级共同资助经费80万

一、声学所介绍 1964年&#xff0c;为落实国家声学规划&#xff0c;满足国家迫切需要&#xff0c;形成全国声学学科研究中心&#xff0c;经国务院副总理聂荣臻元帅批准&#xff0c;成立中国科学院声学研究所。 声学所是从事声学和信息处理技术研究的综合性研究所&#xff0c;…

在React项目中试用Tailwind

TailwindCSS TailwindCSS 是一个套 CSS 的工具类&#xff0c;把常用的功能都进行了定义&#xff0c;下面是一个官网的例子&#xff0c;可以看到Tailwind对一元页面素写了很多类&#xff0c;日常开发中只要定义一两个类就可以搞定类似的功能了。这里写了这么多 p-6 max-w-sm mx…

线程池的核心参数有哪些???

线程池的核心参数包括以下七个&#xff1a; corePoolSize&#xff1a; 这是线程池中的核心线程数&#xff0c;即池中会保留的最少线程数。当提交任务时&#xff0c;如果当前线程数小于核心线程数&#xff0c;线程池会创建新的线程来执行任务。如果当前线程数等于或大于核心线程…

#天空星按键点灯(不中断与中断方式)

&#xff08;1&#xff09;非中断按键点灯 &#xff0c;弹起阻塞&#xff08;天空星的用户按键为PA0&#xff0c;按下高电平&#xff0c;不按下低电平&#xff0c;含有硬件消抖&#xff09; /** 立创开发板软硬件资料与相关扩展板软硬件资料官网全部开源* 开发板官网&#xff1…

MySQL修改数据表的结构

创建数据库 -- create database 创建的数据库名; create database test; 这里创建了一个名为 test 的数据库 选择需要使用的数据库 -- use 数据库名; use test; 这里使用 test 数据库 创建数据表 -- create table 表名(字段名1 数据类型(长度) 约束,字段名2 数据类型(长…

辽宁梵宁教育设计培训:赋能大学生,新技能学习再升级

辽宁梵宁教育设计培训&#xff1a;赋能大学生&#xff0c;新技能学习再升级 在当今这个日新月异、信息爆炸的时代&#xff0c;大学生们面临着前所未有的挑战与机遇。为了帮助他们更好地适应社会的快速变化&#xff0c;提升个人的综合素质和竞争力&#xff0c;辽宁梵宁教育设计…