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/561667.html

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

相关文章

Redis中的慢查询日志(一)

慢查询日志 概述 Redis的慢查询日志功能用于记录执行时间超过给定时长的命令请求&#xff0c;用户可以通过这个功能产生的日志来 监视和优化查询速度。服务器配置有两个和慢查询日志相关的选项: 1.slowlog-log-slower-than选项指定执行时间超过多少微妙(1秒1000 000微妙)的命…

ZeRO论文阅读

一.前情提要 1.本文理论为主&#xff0c;并且仅为个人理解&#xff0c;能力一般&#xff0c;不喜勿喷 2.本文理论知识较为成体系 3.如有需要&#xff0c;以下是原文&#xff0c;更为完备 Zero 论文精读【论文精读】_哔哩哔哩_bilibili 二.正文 1.前言 ①为什么用该技术&…

ctf.show_web14

在switch中&#xff0c;case 里如果没有 break&#xff0c;则会继续向下执行 case。 过滤了information_schema.tables、information_schema.column、空格 information_schema.tables 或 .columns 用反引号 information_schema.tables 同时查3个字段 ?query-1/**/union/**/…

【Python- 包,自定义模块,import】

Python- 包&#xff0c;自定义模块&#xff0c;import ■ 包■ 包创建■ 导入包&#xff0c;模块&#xff0c;函数方法■ __init__.py■ __all__ [my_module1] ■ 自定义模块■ 新建模块■ 导入自定义模块使用■ 导入不同模块的同名功能■ __all__变量 ■ import■ import 模块…

Java 网络编程之TCP(二):基于BIO的聊天室

在上一篇【Java 网络编程之TCP(一)&#xff1a;基于BIO】中&#xff0c;介绍Java中I/O和TCP的基本概念&#xff0c;本文在上文的基础上&#xff0c;实现一个基本的聊天室的功能。 聊天室需求描述&#xff1a; 聊天客户端&#xff1a;发送消息给所有其他客户端&#xff0c;接收…

《剑指 Offer》专项突破版 - 面试题 113、114 和 115 : 详解拓扑排序(C++ 实现)

目录 前言 面试题 113 : 课程顺序 面试题 114 : 外星文字典 面试题 115 : 重建序列 前言 拓扑排序是指对一个有向无环图的节点进行排序之后得到的序列。如果存在一条从节点 A 指向节点 B 的边&#xff0c;那么在拓扑排序的序列中节点 A 出现在节点 B 的前面。一个有向无环…

关于某次授权的大型内网渗透测试(1)

前期渗透&#xff1a; 打点&#xff1a;&#xff08;任意文件上传&#xff09; 直接发现头像处任意文件上传&#xff0c;这里直接上传冰蝎即可。 tasklist查看杀软 System Idle Process 0 N/A System …

细说postgresql之pg_rman备份恢复 —— 筑梦之路

pg_rman是一款开源的备份恢复软件&#xff0c;支持在线和基于PITR的备份恢复方式。 pg_rman类似于oracle的rman&#xff0c;可以进行全量、增量、归档日志的备份。 运行模式&#xff1a; 安装部署 Releases ossc-db/pg_rman GitHub 1、需要根据PG Server的版本&#xff0c;下…

05 MySQL--字段约束、事务、视图

1. CONSTRAINT 约束 创建表时&#xff0c;可以给表的字段添加约束&#xff0c;可以保证数据的完整性、有效性。比如大家上网注册用户时常见的&#xff1a;用户名不能为空。对不起&#xff0c;用户名已存在。等提示信息。 约束包括&#xff1a; 非空约束&#xff1a;not null检…

6.6 完数(project) educoder项目实训

前言 在最近的Python课上&#xff0c;做到这样一个“有趣”的作业&#xff0c;求得前n个完数&#xff0c;并输出其与其真约数的约数的加和式子&#xff0c;刚开始没怎么在意这个题&#xff0c;想着不就是做过好几遍了的语言基础练习题嘛&#xff0c;但是接下来的几小时没想到都…

探索设计模式的魅力:开启智慧之旅,AI与机器学习驱动的微服务设计模式探索

​&#x1f308; 个人主页&#xff1a;danci_ &#x1f525; 系列专栏&#xff1a;《设计模式》 &#x1f4aa;&#x1f3fb; 制定明确可量化的目标&#xff0c;坚持默默的做事。 ✨欢迎加入探索AI与机器学习驱动的微服务设计模式之旅✨ 亲爱的科技爱好者们&#xff0c;有没…

【独家推荐】视频下载神器:一键解决Mac/Win视频下载转换难题!

在信息爆炸的时代&#xff0c;视频已经成为我们获取知识和娱乐的重要途径。然而&#xff0c;很多精彩视频并没有提供直接的下载链接&#xff0c;这就给广大视频爱好者带来了不小的困扰。不过&#xff0c;现在有了这款专为Mac和Windows用户打造的视频下载转换器&#xff0c;一切…

Redux入门:使用@reduxjs/toolkit构建React应用程序状态管理

随着应用程序复杂性的增加,有效管理应用程序状态变得越来越重要。Redux是一种流行的状态管理解决方案,随着应用程序复杂性的增加,有效管理应用程序状态变得越来越重要。Redux是一种流行的状态管理解决方案,但传统的Redux设置和使用过程比较繁琐。幸运的是,Redux官方团队推出了r…

C语言实现贪吃蛇项目(2)

先来看看效果&#xff1a; 20240420_212115 文章目录&#xff1a; 3.项目实现3.0宽字符的打印3.01本地化操作setlocale函数宽字符的打印 3.1贪吃蛇结构的创建和维护3.11贪吃蛇结构的创建3.12贪吃蛇的维护 3.2初始化游戏3.21.打印欢迎界面、隐藏光标和设置窗口大小3.22.绘制地图…

记录好用的python包

记录好用的python包 PipxCentos 安装pipx确保 Pip 被安装更新 Pip安装 Pipx添加 Pipx 到 PATH临时添加到 PATH:永久添加到 PATH: 验证 Pipx 安装 Hatch安装特性 Poetry安装准备工作创建虚拟环境激活虚拟环境安装包追踪 & 更新包常用配置pycharm 远程连接poetry创建的虚拟环…

pycharm创建的项目

pycharm生成django templates删出 settings.py

数据分析_商品维度占比及变化可视化分析(Pandas和Matplotlib)

数据分析_商品维度占比及变化可视化分析(Pandas和Matplotlib) 分析维度包括: 各商品年度销量占比 各商品月度销量变化 构建测试数据 这里你可以了解到: 如何生成时间相关的数据。 如何从列表&#xff08;可迭代对象&#xff09;中生成随机数据。 Pandas 的 DataFrame 自…

IOS 32位调试环境搭建

一、背景 调试IOS程序经常使用gdb&#xff0c;目前gdb只支持32位程序调试&#xff0c;暂不支持IOS 64位程序调试。IOS 32位程序使用GDB调试之前&#xff0c;必须确保手机已越狱&#xff0c;否则无法安装和使用GDB调试软件。下面详细介绍GDB调试IOS 32位程序的环境搭建。 二、I…

数字时代的智慧演奏

数字化时代&#xff0c;工业不再是孤独的机器运转&#xff0c;而是演绎着一场智能与数据的华丽交响。无数智能节点的联动&#xff0c;数据的涌动&#xff0c;成为工业的新活力&#xff0c;同时也是创新的源泉。 工业互联网将每个机器、设备连接在一起&#xff0c;打破了原本独立…

从预训练损失的角度,理解语言模型的涌现能力

原文&#xff1a;Understanding Emergent Abilities of Language Models from the Loss Perspective 摘要 本文从预训练损失的角度重新审视语言模型的涌现能力&#xff0c;挑战了以往以模型大小或训练计算量为标准的观念。通过实验&#xff0c;作者发现预训练损失是预测下游任…