美文网首页
玩一玩vector吧~

玩一玩vector吧~

作者: zhou的技术小庄园 | 来源:发表于2021-08-27 00:05 被阅读0次

    (关于前几篇文章埋下的坑)

    自作者开始浅谈STL以来,虽然只出过STL的内存管理方式,但是讲到的东西真的远远不及他里面的内容,只是很浅的谈论里面的一些做法而已。而真正的内存管理,我也在前面几篇文章中说到,这个是一个非常大的话题,或许在座的读者是刚刚经历了面试的应届生,或许您的面试官会或多或少的问过关于一些c++内存管理的事情,但是网上很多很多的答案都是非常肤浅的回答与描述。如果作者在接下来的几个月中时间充裕的话,我会真的下定决心,我们来浅谈一下c++的内存管理,这个真的是一个大话题,或者作者也把控不住。(不要问我为什么要那么执着于内存、那么推崇c/c++,那是我认为,每一个程序员,真正的功底,也许您现在不太看好c/c++,认为java才是天下无敌,那么您直接退出此文章即可。)

    前述

    这篇文章也需要一些前置知识:您至少得使用过STL的一种容器,会c++的基本语法,什么叫模板等。
    在讲我们接下来的主题之前,我们来探讨一件事情,在我们没有接触到容器之前,我们一般在定义一个一定容量的数据单元的时候,首先想到的,那便是数组,但是数组有一个较大的缺点,那就是一旦我们确定下来数组的大小,那便不会再改变,如果我们还想继续扩充容量,我们只好重新定义一个,然后赋值,这显然是在容器推出之前,我们普遍的做法,即使在c99之后,推出了可变长数组,通常可变长数组一般不占大小,但是一旦确定大小之后,也不能在改变,这个也没有根本的解决我们的问题。有没有一种方法,可以让我定义一个数据单元,我可以一直在里面放东西,我不需要提前设置他的大小,只要我还在使用,我就可以一直放东西?
    当然有,而且今天我们就要讲其中的一种,那便是vector。

    vector的自我介绍

    vector,顾名思义,那便是向量嘛,所谓向量,那便是,有大小,有方向的量,vector也是向量,他的大小可变,当然它也有方向:左闭右开嘛。它相对于array而言,array一旦确定了大小,便不可改变,是一个静态的量,而vector可以变化,是一个动态的量,随着我们新元素的加入,其内部空间会随着其内部动态增长机制不断的变化。

    vector内部实现(常用的)

    //vector的第二参数代表他的内存分配器alloc,这个作者已经讲过,也展示过其内部实现与他的原理,见以前的文章
    //第二参数可以改变,这个只是它默认的空间分配器而已
    template<class T,class Alloc = alloc>
    class vector
    { 
      public:
        typedef   T                   value_type;//元素类型
        typedef   value_type*         pointer;//指针
        typedef   value_type*         iterator;//迭代器,可见,vector里的迭代器其实就是指针,但不能说迭代器济就是指针
        typedef   value_type&         reference;//引用
        typedef   size_t              szie_type;//大小
        typedef   ptrdiff_t           difference_type;//表示指针之间的距离的一种安全方式
      protected:
        typedef simple_alloc<value_type,Alloc>data_allocator;//默认分配器
        iterator start;//正在使用的空间头部
        iterator finish;//当前最后一个元素的下一个位置
        iterator end_of_storage;//整个空间的尾部
      //在position指定的位置上插入一个元素
        void insert_aux(iterator position, const T& x);
    
        void deallocate()
        { 
            if (start)
            {
                data_allocator::deallocate(start, end_of_storage - start);
            }
        }
    
        void fill_initialize(size_type n, const T& value)
        {
            start = allocate_and_fill(n, value);
            finish = start + n;
            end_of_storage = finish;
        }
    
          iterator allocate_and_fill(size_type n, const T& value)
          {
              iterator result = data_allocator::allocate(n);
              uninitalized_fill_n(result, n, value);//从result开始,用value初始化,大小为n
              return result;
          }
      public://常用函数
          iterator begin()  { return start;}
          iterator end()  { return finish;}
          size_type size()  {  return size_type(end() - begin());}
          size_type capacity() const { return end_of_storage - begin(); }
          bool empty() const { return begin() == end();}
          reference operator[] (size_type n) { return *(begin() + n);}
          
          vector():start(0), finish(0),end_of_storage(0){}
          vector(size_type n, const T& value){ fill_initialize(n, value);}
          vector(int n, const T& value){ fill_initialize(n, value);}
          vector(long n, const T& value){ fill_initialize(n, value);}
          explicit vector(size_type n){ fill_initialize(n, T());}//避免隐式转换
          
          ~vector()
          { 
              destory(start, finish);//全局函数,从start到finish,调用vector的析构函数
              deallocate();
          }
    
          reference front() { return *begin();}
          reference back() { return *(end() - 1);}
    
          void push_back(const T&  x)//插入元素
          { 
              if  (finish != end_of_storage)
              { 
                  construct(finish, x);//在finish的位置上调用placenew;
                  ++finish;
              }
              else
              {
                  insert_aux(end(),x);
              }
          }
        
          void pop_back()
          {
              --finish;
              destory(finish);//调用finish这个位置上的析构函数
          }
    //删除某一位置上的元素
          iterator erase(iterator position)
          {
              if (position + 1 != end())
              {
                  copy(position + 1, finish, position);//position之后的元素wangle前移动
              }
              --finish;
              destory(finish);
              return position;
          }
          
          void resize(size_type new_szie, const T& value)
          {
              if (new_szie < size())
              {
                  erase(begin() + new_szie, end());//这个是算法库中函数,移除从a->b之间的元素
              }
              else
              {
                  insert(end(), new_size - size(), value);//算法库中函数,插入从A->B之间,用value初始化
              }
          }
    ··//函数重载,仔细看区别
          void resize(size_type new_size)
          {
              return (resize(new_szie, T());
          }
    };
    template<class T, class Alloc>
    void vector<T, Alloc>::insert_aux(iterator position, const T& x)
        {
            if  (finish != end_of_stroage)//当前空间还有剩余
            {
                constrcut(finish,*(finish - 1));
                ++finish;
                T x_copy = x;
                copy_backward(position,finish - 2, finish - 1);
                *position = x_copy;
            }
            else//当前空间没有剩余
            {
                const size_type old_szie = size();
                const size_typoe len = old_size != 0 ? 2*old_size : 1;//两倍扩展,在linux中是1.5倍
                iterator new_start = data_alloctor::allocate(len);
                iterator new_finish = new_start;
              //回滚机制
                try{
                    //将旧的vector中的元素拷贝到新的vector中
                    new_finish = uninitialzed_copy(start, position, new_start);
                    construct(new_satrt,x);//设初值
                    ++finish;
                    new_finish =  uninitialzed_copy(position, finish, new_start);//安插点的原内容也拷贝过来
                }
                catch(...)
                {
                    //一旦发现有异常,那么直接回滚,将申请的空间全部毁掉
                    destory(new_start, new_finish);
                    data_allocator::deallocate(new_start, len);
                    throw;
                }
                destory(begin(), end());
                deallocate();
                start = new_start;
                finish = new_finish;
                end_of_storage = new_start + len;
            }
        }
    

    总结

    看这个,比你看面经直接了当的多吧~(作者很讨厌看面经,这种感觉就想拾人牙慧),与其去看别人的总结,倒不如去看真正的源码。有些函数在前几篇文章中,有其声明与实现,没有的,我已经补充其作用了!

    相关文章

      网友评论

          本文标题:玩一玩vector吧~

          本文链接:https://www.haomeiwen.com/subject/zchpiltx.html