从零开始的C++(十一)

这篇具有很好参考价值的文章主要介绍了从零开始的C++(十一)。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

vector的模拟实现:

1.构造函数:


            vector()
            {

             }

            vector(int n, const T& value = T())
            {   
                reserve(n);
                for (int i = 0; i < n; i++)
                {
                    push_back(value);
                }
            }

            template<class InputIterator>

            vector(InputIterator first, InputIterator last)
            {  
                auto it = first;
                while (it != last)
                {
                    push_back(*it);
                    it++;
                }
            }
            void swap(iterator&v1,iterator&v2)
            {
                iterator ret = v1;
                v1 = v2;
                v2 = ret;
            }

            vector(const vector<T>& v)
            {
                vector<T>tmp(v.cbegin(), v.cend());
                swap(_start,tmp._start);
                swap(_finish, tmp._finish);
                swap(_endOfStorage, tmp._endOfStorage);
            }
       private:

           iterator _start = nullptr; // 指向数据块的开始

           iterator _finish = nullptr; // 指向有效数据的尾

           iterator _endOfStorage = nullptr; // 指向存储容量的尾

对象的成员使用了参数列表,防止随机值引发异常。同时,对于传同类型对象的构造函数,复用了传迭代器的构造函数创建临时对象,然后交换this所指对象和临时对象的成员的值,防止浅拷贝,并且利用临时变量销毁原本this对象的成员的内容。

2.赋值重载:

     vector<T>& operator= (vector<T> v)
            {
                swap(_start, v._start);
                swap(_finish, v._finish);
                swap(_endOfStorage, v._endOfStorage);

                return *this;
             }

赋值重载的原理和拷贝构造类似,都是用临时对象交换赋值,此处不用创建临时对象的原因是在实参到形参的过程已经进行了拷贝构造,即此处形参就是临时对象,所以直接交换即可。

3.插入和删除

  void push_back(const T& x)
            {
                if (size() == capacity())
                {
                    reserve(size() * 2+1);
                }
                *(_finish) = x;
                _finish++;
            }
           
            void pop_back()
            {
                assert(size() > 0);
                _finish--;
            }

            void swap(vector<T>& v)
            {
                swap(_start, v._start);
                swap(_finish, v._finish);
                swap(_endOfStorage, v._endOfStorage);
            }

            iterator insert(iterator pos, const T& x)
            {   
                assert(pos-_start <= size());
                assert(pos - _start>= 0);
                if (size() == capacity())
                {  
                    int sz = pos - _start;
                    reserve(size() * 2+1);
                    pos = _start + sz;
                }

                auto it = _finish-1;
                while (it >= pos)
                {
                    *(it + 1) = *it;
                    it--;
                }
                *pos = x;

                _finish++;
                return pos;
            }

            iterator erase(iterator pos)
            {   
                assert(pos-_start >= 0);
                assert(pos-_start < size());
                auto it = pos+1;
                while (it != _finish)
                {
                    *(it - 1) = *(it);
                    it++;
                }
                --_finish;
                   
                return pos;
             }

需要注意的是,insert和erase都可能会造成迭代器失效(即迭代器使用结果可能未定义或无法使用)。同时也需要注意判断插入、删除是否合理(是否越界等)。

4.扩容


            void reserve(size_t n)
            {
                if (n >capacity())
                {    
                    int sz = size();
                    iterator tmp = new T[n];
                    if (_start!=nullptr)
                    {
                        //值拷贝
                        for (int i = 0; i < sz; i++)
                        {
                            tmp[i] = _start[i];
                        }
                    }
                    delete[]_start;
                    //更新
                    _start = tmp;
                    _endOfStorage = _start + n;
                    _finish = _start + sz;
                }
            }

            void resize(size_t n, const T& value = T())
            {
                if (n <=size())
                {
                    _finish = _start + n;
                }
                else
                {
                    reserve(n);
                    while (size() < n)
                    {
                        push_back(value);
                    }

                }




            }

扩容应注意是深拷贝,因为成员可能是自定义类型,有自己的析构函数,如果是浅拷贝可能会出现二次delete的情况,也可能会出现析构导致内容变成随机值无法正常使用。文章来源地址https://www.toymoban.com/news/detail-723002.html

到了这里,关于从零开始的C++(十一)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 从零开始的力扣刷题记录-第六十一天

    题目描述: 给定由一些正数(代表长度)组成的数组 nums ,返回 由其中三个长度组成的、面积不为零的三角形的最大周长 。如果不能形成任何面积不为零的三角形,返回 0。 题解: 排序后从后往前遍历,取最大的三个边,如果满足两边之和大于第三边则返回,否则整体向前

    2024年02月09日
    浏览(35)
  • 【从零开始学习JAVA | 第四十一篇】深入JAVA锁机制

    目录 前言:          引入: 锁机制:  CAS算法: 乐观锁与悲观锁: 总结: 在多线程编程中,线程之间的协作和资源共享是一个重要的话题。当多个线程同时操作共享数据时,就可能引发数据不一致或竞态条件等问题。为了解决这些问题,Java提供了强大的锁机制,使得

    2024年02月14日
    浏览(40)
  • 【从零开始学习JAVA | 第二十一篇】常见API介绍 System

    目录 前言: System: System类中静态方法: 总结:                 system 是一个很底层的 API,是一个工具类, 提供了一些与系统相关的方法 。他在我们写项目的时候提供了一些非常实用的方法,本篇将会介绍一些实用的system API 的方法调用。 System类是Java语言提供的一个

    2024年02月15日
    浏览(36)
  • 【从零开始vnpy量化投资】十一. 实盘接入测试与正式实盘

    【从零开始vnpy量化投资】十一. 实盘接入测试与正式实盘 本篇主要讲解如何使用vnpy进行实盘交易,由于上一节我们已经学习了模拟盘运行,如果一切顺利的话,只需要通过穿透测试,就可以正式部署实盘了。 这里笔者推荐读者尽量多联系不同期货公司的业务员或者居间人,

    2024年02月07日
    浏览(22)
  • 《Netty》从零开始学netty源码(五十一)之PoolArena的内存释放与扩容

    当chunk使用完毕后需要释放,如果是池化chunk则需要放回池中供下次循环利用,如果是非池化的则直接释放对应的物理空间。 下面继续分析释放具体物理空间的destroyChunk()方法和释放chunk的freeChunk()方法。 destroyChunk() 该方法为抽象方法,由具体实现类实现,以DirectArena为例 fre

    2024年02月02日
    浏览(28)
  • 从零开始学习 Java:简单易懂的入门指南之IO字符流(三十一)

    当使用字节流读取文本文件时,可能会有一个小问题。就是遇到中文字符时,可能不会显示完整的字符,那是因为一个中文字符可能占用多个字节存储。所以Java提供一些字符流类,以字符为单位读写数据,专门用于处理文本文件。 java.io.Reader 抽象类是表示用于读取字符流的

    2024年02月08日
    浏览(27)
  • 从零开始学习 Java:简单易懂的入门指南之抽象类&接口&内部类(十一)

    1.1.1 抽象类引入 ​ 父类中的方法,被它的子类们重写,子类各自的实现都不尽相同。那么父类的方法声明和方法主体,只有声明还有意义,而方法主体则没有存在的意义了(因为子类对象会调用自己重写的方法)。换句话说,父类可能知道子类应该有哪个功能,但是功能具体怎

    2024年02月13日
    浏览(23)
  • 从零开始学习 Java:简单易懂的入门指南之Collection集合及list集合(二十一)

    1.1数组和集合的区别 相同点 都是容器,可以存储多个数据 不同点 数组的长度是不可变的,集合的长度是可变的 数组可以存基本数据类型和引用数据类型 集合只能存引用数据类型,如果要存基本数据类型,需要存对应的包装类 1.2集合类体系结构 1.3Collection 集合概述和使用 Collec

    2024年02月10日
    浏览(26)
  • 【前端】从零开始读懂Web3

    用心生活,用力向上,微笑前行,就是对生活最好的回馈。  本专栏说明: 主要是记录在分享知识的同时,不定时给大家送书的活动。 参与方式: 赠书数量:本次送书 3 本,评论区抽3位小伙伴送书 活动时间: 截止到 2023-04-20 20:00:00 抽奖方式: 利用程序进行抽奖。 参与方

    2023年04月18日
    浏览(28)
  • 从零开始的C++(六)

    1.类和对象补充: 静态成员,有静态成员函数和静态成员变量,特点是不为类的某个对象所有,而是为同类所有对象共有。因为是为同类对象共同拥有,所以计算对象的大小的时忽略静态成员。因为静态成员是放在静态区,对象的作用只是确定类域,所以(类名*)0-静态成员

    2024年02月07日
    浏览(31)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包