热门标签 | HotTags
当前位置:  开发笔记 > 运维 > 正文

C++STLvector的模拟实现

这篇文章主要介绍了C++STLvector的模拟实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧

1. vector的介绍和使用

  • vector是表示可变大小数组的序列容器。
  • 就像数组一样,vector也采用的连续存储空间来存储元素。也就是意味着可以采用下标对vector的元素进行访问,和数组一样高效。但是又不像数组,它的大小是可以动态改变的,而且它的大小会被容器自动处理。
  • 本质讲,vector使用动态分配数组来存储它的元素。当新元素插入时候,这个数组需要被重新分配大小为了增加存储空间。其做法是,分配一个新的数组,然后将全部元素移到这个数组。就时间而言,这是一个相对代价高的任务,因为每当一个新的元素加入到容器的时候,vector并不会每次都重新分配大小。
  • vector分配空间策略:vector会分配一些额外的空间以适应可能的增长,因为存储空间比实际需要的存储空间更大。不同的库采用不同的策略权衡空间的使用和重新分配。但是无论如何,重新分配都应该是对数增长的间隔大小,以至于在末尾插入一个元素的时候是在常数时间的复杂度完成的。
  • 因此,vector占用了更多的存储空间,为了获得管理存储空间的能力,并且以一种有效的方式动态增长。
  • 与其它动态序列容器相比(deques, lists and forward_lists), vector在访问元素的时候更加高效,在末尾添加和删除元素相对高效。对于其它不在末尾的删除和插入操作,效率更低。比起lists和forward_lists统一的迭代器和引用更好。

更为详细的可以查看vector文档介绍。

2. vector的模拟实现

vector的嵌套型别定义

typedef _Ty         value_type;
typedef value_type* iterator;
typedef value_type& reference;
typedef size_t      size_type;

vector的成员变量

private:
        iterator _start;
        iterator _last;
        iterator _end;

2.1 vector构造函数和拷贝构造函数

vector():_start(nullptr),_last(nullptr),_end(nullptr)
{}
vector(size_type n,const _Ty& value):_start(nullptr),_last(nullptr),_end(nullptr)
{
     insert(n,value);
}
vector(iterator f,iterator l):_start(nullptr),_last(nullptr),_end(nullptr)
{
     insert(f,l);
}   
vector(const vector& iv)
{
        reserve(iv.capacity());
        iterator it = begin();
        iterator vit = iv.end();
        while (vit != iv.begin())
        {
              *it++ = *vit--;     
        }
}

2.2 insert函数和eraser函数

iterator insert(iterator pos,const _Ty& value)
{
    //1.当size()==capacity()时,表明vector已满,再进行插入前需要进行扩容
    if(size()== capacity())
    {
        size_type oldpos = pos - begin();
        //这里需要防止一种情况:若vector为空的时候,他的capacity为0,这个时候给他直接扩容2倍是行不通的,
        //因为2*0 = 0,因此就需要进行判断 
        size_type newcapacity = (capacity() == 0)? 1 : 2*capacity();

        reserve(newcapacity);

        //这里空间发生了变化,pos迭代器会失效,因此需要重新对pos进行设置
        //reserve不会使vector的成员变量失效
        pos = begin() + oldpos;
    }
    //2.当size()  pos)
    {
        *tail = *(tail-1);
        --tail;
    }
    //这里要注意的是挪动数据时,因为没有对pos位置进行操作,所以pos位置的迭代器并没有失效,
    //但是pos位置之后的迭代器全部失效了,但在这里并没有关系,我们并不会用到那些迭代器
    *pos = value;

    //插入完之后,一定要对_last指针+1,因为全部向后挪动了一个元素
    ++_last;

    return pos;
}

void insert(size_type n,const _Ty& value)
{
    for(int i = 0;i = _start || pos <_last);
    //1.删除pos位置的元素,就是将[pos,end()]这个区间向前挪动一个即可
    iterator it = pos + 1;
    while(it != _last)
    {
        *(it-1) = *(it);
        ++it;
    }

    --_last;
    return pos;
}

2.3 reserve函数和resize函数

void reserve(size_type n)
{
    //若 n 的值大于vector的容量,则开辟空间
    //若 n 的值小于等于,则不进行任何操作
    if(n > capacity())
    {
        //1.新开辟一个空间
        size_type oldSize = size();
        _Ty* newVector = new _Ty[n];
        //2.将原空间的数值赋值到新空间
        if(_start)
        {
            //注意:这里不能使用memcpy,因为memcpy是一个浅拷贝。
            //memcpy(newVector,_start,sizeof(_Ty)*size());
            for(size_type i = 0; i  capacity())
    {
        reserve(n);
    }
    //若当n的值大于size()而小于capacity()的时候,只需将_last的指针往后移即可

    iterator it = _last;
    _last = _start + n;

    while(it != _last)
    {
        *it = value;
        ++it;
    }
    //resize()函数也不需要担心迭代器失效的问题
}

2.4 push_back函数和pop_back函数

void push_back(const _Ty& value)
{
    insert(end(),value);
}
void pop_back()
{
    erase(end()-1);
}

2.5 begin函数和end函数

iterator begin()const
{
    return _start;
}
iterator end() const
{
    return _last;
}
 

2.6 size函数、capacity函数

size_type size()
{
    return end()-begin();
}
size_type capacity()const
{
    return _end-begin();
}
 

2.7 empty函数和operator[]重载

bool empty()const
{
    return end() == begin();
}

reference operator[](size_type n)
{
    return *(begin() + n);
}
 

2.8 完整代码和相应测试

#include 
#include 

using namespace std;


namespace mytest{
    template
    class vector
    {
        public:
            typedef _Ty         value_type;
            typedef value_type* iterator;
            typedef value_type& reference;
            typedef size_t      size_type;
        public:
            iterator begin()const
            {
                return _start;
            }
            iterator end() const
            {
                return _last;
            }
            size_type size()
            {
                return end()-begin();
            }
            size_type capacity()const
            {
                return _end-begin();
            }
            bool empty()const
            {
                return end() == begin();
            }
            reference operator[](size_type n)
            {
               return *(begin() + n); 
            }

        public:
            vector():_start(nullptr),_last(nullptr),_end(nullptr)
            {}
            vector(size_type n,const _Ty& value):_start(nullptr),_last(nullptr),_end(nullptr)
            {
                insert(n,value);
            }
            vector(iterator f,iterator l):_start(nullptr),_last(nullptr),_end(nullptr)
            {
                insert(f,l);
            }   
            vector(const vector& iv)
            {
                reserve(iv.capacity());
                iterator it = begin();
                iterator vit = iv.end();
                while (vit != iv.begin())
                {
                    *it++ = *vit--;     
                }
            }
        public:
            void reserve(size_type n)
            {
                //若 n 的值大于vector的容量,则开辟空间
                //若 n 的值小于等于,则不进行任何操作
                if(n > capacity())
                {
                    //1.新开辟一个空间
                    size_type oldSize = size();
                    _Ty* newVector = new _Ty[n];
                    //2.将原空间的数值赋值到新空间
                    if(_start)
                    {
                        //注意:这里不能使用memcpy,因为memcpy是一个浅拷贝。
                        //memcpy(newVector,_start,sizeof(_Ty)*size());
                        for(size_type i = 0; i  capacity())
                {
                    reserve(n);
                }
                //若当n的值大于size()而小于capacity()的时候,只需将_last的指针往后移即可
                
                iterator it = _last;
                _last = _start + n;

                while(it != _last)
                {
                    *it = value;
                    ++it;
                }
                //resize()函数也不需要担心迭代器失效的问题
            }

            void push_back(const _Ty& value)
            {
                insert(end(),value);
            }
            void pop_back()
            {
                erase(end()-1);
            }

            

            iterator insert(iterator pos,const _Ty& value)
            {
                //1.当size()==capacity()时,表明vector已满,再进行插入前需要进行扩容
                if(size()== capacity())
                {
                    size_type oldpos = pos - begin();
                    //这里需要防止一种情况:若vector为空的时候,他的capacity为0,
                    //这个时候给他直接扩容2倍是行不通的,因为2*0 = 0,因此就需要进行判断 
                    size_type newcapacity = (capacity() == 0)&#63; 1 : 2*capacity();

                    reserve(newcapacity);

                    //这里空间发生了变化,pos迭代器会失效,因此需要重新对pos进行设置
                    //reserve不会使vector的成员变量失效
                    pos = begin() + oldpos;
                }
                //2.当size()  pos)
                {
                    *tail = *(tail-1);
                    --tail;
                }
                //这里要注意的是挪动数据时,因为没有对pos位置进行操作,所以pos位置的迭代器并没有失效,
                //但是pos位置之后的迭代器全部失效了,但在这里并没有关系,我们并不会用到那些迭代器
               *pos = value;

               //插入完之后,一定要对_last指针+1,因为全部向后挪动了一个元素
               ++_last;

               return pos;
            }

            void insert(size_type n,const _Ty& value)
            {
                for(int i = 0;i = _start || pos <_last);
                //1.删除pos位置的元素,就是将[pos,end()]这个区间向前挪动一个即可
                iterator it = pos + 1;
                while(it != _last)
                {
                    *(it-1) = *(it);
                    ++it;
                }

                --_last;
                return pos;

            }

 

            

        private:
            iterator _start;
            iterator _last;
            iterator _end;
    };

};

void Test1()
{
    mytest::vector iv;

    cout <<"iv.size() = " < iv(10,2); 
    mytest::vector::iterator it = iv.begin();
    while(it != iv.end())
    {
        cout <<*it <<" ";
        ++it;
    }
    cout < iv(ar,ar+6);
    mytest::vector::iterator it = iv.begin();
    while(it != iv.end())
    {
        cout <<*it <<" ";
        ++it;
    }
    cout <

到此这篇关于C++ STL vector的模拟实现的文章就介绍到这了,更多相关C++ STL vector内容请搜索以前的文章或继续浏览下面的相关文章希望大家以后多多支持!


推荐阅读
  • PBO(PixelBufferObject),将像素数据存储在显存中。优点:1、快速的像素数据传递,它采用了一种叫DMA(DirectM ... [详细]
  • 本文介绍了如何使用Postman构建和发送HTTP请求,包括四个主要部分:方法(Method)、URL、头部(Headers)和主体(Body)。特别强调了Body部分的重要性,并详细说明了不同类型的请求体。 ... [详细]
  • 本文介绍了在 iOS 开发中设置图片和视图圆角的几种方法,包括通过 layer 设置圆角、使用贝塞尔曲线和 Core Graphics 框架,以及使用 CAShapeLayer 和 UIBezierPath。每种方法都有其优缺点,适用于不同的场景。 ... [详细]
  • iOS snow animation
    CTSnowAnimationView.hCTMyCtripCreatedbyalexon1614.Copyright©2016年ctrip.Allrightsreserved.# ... [详细]
  • 如何解决TS1219:实验性装饰器功能可能在未来版本中更改的问题
    本文介绍了两种方法来解决TS1219错误:通过VSCode设置启用实验性装饰器,或在项目根目录下创建配置文件(jsconfig.json或tsconfig.json)。 ... [详细]
  • 本文讨论了在 Oracle 10gR2 和 Solaris 10 64-bit 环境下,从 XMLType 列中提取数据并插入到 VARCHAR2 列时遇到的性能问题,并提供了优化建议。 ... [详细]
  • 本文整理了一份基础的嵌入式Linux工程师笔试题,涵盖填空题、编程题和简答题,旨在帮助考生更好地准备考试。 ... [详细]
  • packagecom.panchan.tsmese.utils;importjava.lang.reflect.ParameterizedType;importjava.lang. ... [详细]
  • 通过马老师的视频学习了Java中的容器相关内容,包括Collection、Set、List、Map及其常见实现类,并深入了解了这些容器的基本操作方法。 ... [详细]
  • 使用HTML和JavaScript实现视频截图功能
    本文介绍了如何利用HTML和JavaScript实现从远程MP4、本地摄像头及本地上传的MP4文件中截取视频帧,并展示了具体的实现步骤和示例代码。 ... [详细]
  • 【线段树】  本质是二叉树,每个节点表示一个区间[L,R],设m(R-L+1)2(该处结果向下取整)左孩子区间为[L,m],右孩子区间为[m ... [详细]
  • 在 iOS 设备上使用系统 API 进行视图截图时,有时会遇到图片拼接处出现白边的问题。 ... [详细]
  • iOS 不定参数 详解 ... [详细]
  • iOS开发 - 解决导航栏子视图损坏问题
    本文介绍了一个在Xcode 5.0.2和iOS 7模拟器环境下,使用Storyboard创建CoreData CRUD应用时遇到的导航栏子视图损坏问题及其解决方案。 ... [详细]
  • Visual Studio 2019 安装指南
    作为一名拥有三年经验的程序员,由于长期专注于C语言,我意识到自己的技术栈过于单一。在转型为Android驱动开发工程师后,这种局限性更加明显。本文将介绍如何安装Visual Studio 2019,并配置C++开发环境,以帮助读者拓宽技术视野。 ... [详细]
author-avatar
吴小彬x
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有