玩一玩vector吧~

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

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

前述

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

vector的自我介绍

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

vector内部实现(常用的)

//vector的第二参数代表他的内存分配器alloc,这个作者已经讲过,也展示过其内部实现与他的原理,见以前的文章
//第二参数可以改变,这个只是它默认的空间分配器而已
template
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_allocdata_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
void vector::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吧~)