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

news2024/11/17 23:45:54

      在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.coloradmin.cn/o/1621354.html

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

相关文章

国密SSL证书在等保、关保、密评合规建设中的应用

在等保、关保、密评等合规建设中&#xff0c;网络和通信安全方面的建设是非常重要的部分&#xff0c;需要实现加密保护和安全认证&#xff0c;确保传输数据机密性、完整性以及通信主体可信认证。国密SSL证书应用于等保、关保和密评合规建设中&#xff0c;不仅能够提升网络信息系…

创建第一个Vue3项目时遇到的报错及处理

其实主要就是针对命令&#xff1a;npm init vuelatest 的报错处理 受限自己电脑本身已经安装了node&#xff0c;npm&#xff0c;在环境搭建时&#xff0c;遇到了报错&#xff0c;如下&#xff1a; 我以为是这是个很简单的问题&#xff0c;看起来是npm的版本过低&#xff0c;升…

测试用例设计方法-探索性测试

生活犹如骑单车&#xff0c;唯有前进才能保持平衡。大家好&#xff0c;今天给大家分享一下关于探索性测试的方法&#xff0c;在探索性测试中更加考验测试人员的经验&#xff0c;所以我们在平时的测试工作中一定要多记录、多总结、多复盘&#xff0c;对于经常出现的bug深究其根本…

找对方法,单位信息宣传工作向媒体投稿其实也简单

曾经,作为一名肩负单位信息宣传重任的我,每当面对那堆叠如山的稿件与闪烁不定的电脑屏幕,心中总会涌起一股无尽的焦虑与疲惫。尤其在向媒体投稿这个环节,我仿佛陷入了一个难以挣脱的漩涡,邮箱投稿的艰辛、审核的严苛、出稿的迟缓以及成功发表的少之又少,如同一座座无形的大山压…

SpringBoot整合阿里云实现图片的上传管理

唠嗑部分 各位小伙伴大家好&#xff0c;我是全栈小白&#xff0c;之前我们分享了一期SpringBoot如何整合七牛云存储实现图片的上传与存储&#xff0c;今天我们接着分享一下SpringBoot整合阿里云OSS实现图片的上传与存储 言归正传 一、阿里云账号注册 阿里云OSS文件存储是免…

一键生成数据库文档,从此告别人工整理文档

背景 在我们日常开发过程中&#xff0c;常常遇到项目需要出一个数据库文档&#xff0c;面对数据表众多的场景一个一个写显然不现实&#xff0c;于是 screw工具很好的满足了我们的需求&#xff0c;从此告别人工整理文档; screw工具它可以将整个数据库的表输出为数据库表结构文档…

【Java--数据结构】提升数据处理速度!深入理解Java中的顺序表机制

欢迎关注个人主页&#xff1a;逸狼 创造不易&#xff0c;可以点点赞吗~ 如有错误&#xff0c;欢迎指出~ 目录 两种创建顺序表的方法及区别 认识ArrayList的构造方法 不带参数的构造方法 带参数的构造方法 利用Collection 构造方法 举例 ArrayList 常用方法演示 add addAll remo…

实战技巧:Android 14适配从挂号到出院

公众号「稀有猿诉」 原文链接 实战技巧&#xff1a;Android 14适配从挂号到出院 啥&#xff1f;这都4202年了&#xff0c;你的应用还没有升级到targetSDK 34&#xff1f;莫慌&#xff0c;本文就带着你全面的了解升级targetSDK 34的方法以及避坑指南。 注意&#xff0c;A…

基于SpringBoot+Vue网上商城系统的设计与实现

系统介绍 随着社会的不断进步与发展&#xff0c;人们经济水平也不断的提高&#xff0c;于是对各行各业需求也越来越高。特别是从2019年新型冠状病毒爆发以来&#xff0c;利用计算机网络来处理各行业事务这一概念更深入人心&#xff0c;由于用户工作繁忙的原因&#xff0c;去商…

《看漫画学C++》背后的故事1:艺术与科技的结合

引言&#xff1a; 在数字化浪潮中&#xff0c;艺术与科技的结合催生了无数创新。《看漫画学C》正是这一跨界合作的产物&#xff0c;它不仅是一本编程书籍&#xff0c;更是艺术与科技融合的典范。 一、相遇&#xff1a; 科技与艺术的火花作为一名专注于技术的软件程序员&…

【Python】Python函数的黑魔法:递归,嵌套函数与装饰器

欢迎来到CILMY23的博客 本篇主题为&#xff1a; Python函数的黑魔法&#xff1a;递归&#xff0c;嵌套函数与装饰器 个人主页&#xff1a;CILMY23-CSDN博客 系列专栏&#xff1a;Python | C | C语言 | 数据结构与算法 感谢观看&#xff0c;支持的可以给个一键三连&#xff…

五、e2studio VS STM32CubeIDE之汉化

目录 一、概述/目的 二、stm32cubeide汉化 2.1 在线下载安装汉化插件 2.2 直接安装汉化包(推荐) 三、e2studio STM32CubeIDE中英文切换 五、e2studio VS STM32CubeIDE之汉化 一、概述/目的 介绍stm32cubeide汉化方案和汉化包 e2studio自带汉化包&#xff0c;在安装过程中…

代理IP供应商的代理池大小怎么看?

代理池作为网络爬虫、数据采集和隐私保护等领域中的重要工具&#xff0c;扮演着连接真实网络和爬虫之间的桥梁。代理池的大小是影响其性能和可用性的关键因素之一。在这篇文章中&#xff0c;我们将深入探讨代理池的大小对业务的影响&#xff0c;并探讨在不同情况下如何选择合适…

AI-数学-高中-43常见函数的导数

原作者视频&#xff1a;【导数】【一数辞典】2常见函数的导数_哔哩哔哩_bilibili

OpenHarmony语言基础类库【@ohos.url (URL字符串解析)】

说明&#xff1a; 本模块首批接口从API version 7开始支持。后续版本的新增接口&#xff0c;采用上角标单独标记接口的起始版本。 导入模块 import Url from ohos.url URLParams9 URLParams接口定义了一些处理URL查询字符串的实用方法。 constructor9 constructor(init?…

【注释和反射】类加载的过程

继上一篇博客【注释和反射】获取class类实例的方法-CSDN博客 目录 三、类加载的过程 例子 三、类加载的过程 在Java虚拟机&#xff08;JVM&#xff09;中&#xff0c;类加载是一个将类的字节码文件从文件系统或其他来源加载到JVM的内存中&#xff0c;并将其转换为类或接口的…

SEW减速机参数查询 2-2 实践

首先说说结论&#xff1a;在不和SEW官方取得沟通之前&#xff0c;你几乎无法直接通过查阅SEW官方文档得到相关减速机的所有技术参数&#xff1a;比如轴的模数和齿数&#xff0c;轴承的参数。我在周一耗费了一个上午&#xff0c;最终和SEW方面确认后才知晓相关技术参数需要凭借销…

LeetCode 1052. 爱生气的书店老板

题目链接 https://leetcode.cn/problems/grumpy-bookstore-owner/description/?envTypedaily-question&envId2024-04-23 先把最初的满意人数累加算出来&#xff0c;然后使用滑动窗口来模拟连续 minutes分钟不生气&#xff0c;计算不生气minutes分钟最大的满意数 class S…

2010-2023年“国家级大数据综合试验区”试点城市DID匹配数据

2010-2023年国家级大数据综合试验区试点城市DID匹配数据 1、时间&#xff1a;2010-2023年 2、来源&#xff1a;国家发展改革委、工业和信息化部、ZY网信办发函批复的试验区 3、指标&#xff1a;行政区划代码、年份、所属省份、地区、国家级大数据综合试验区、最早设立年份 …

基于Google Gemini 探索大语言模型在医学领域应用评估和前景

概述 近年来&#xff0c;大规模语言模型&#xff08;LLM&#xff09;在理解和生成人类语言方面取得了显著的飞跃&#xff0c;这些进步不仅推动了语言学和计算机编程的发展&#xff0c;还为多个领域带来了创新的突破。特别是模型如GPT-3和PaLM&#xff0c;它们通过吸收海量文本…