zoukankan      html  css  js  c++  java
  • vector的实现细节

    1、vector类的主要数据成员

    vector是动态空间,随着元素的加入,它的内部机制会自行扩充空间以容纳新元素。

    vector类中主要有三根指针start, finish和end_of_storage

     1 template <typename T>
     2 class vector
     3 {
     4 public:
     5     typedef T value_type;
     6     typedef value_type* iterator;
     7     ...  
     8 protected:
     9     iterator start;
    10     iterator finish;
    11     iterator end_of_storage;
    12     ...
    13 };

    其中start是指向当前使用空间的起始位置

          finish是指向当前使用空间末尾元素的下一个位置

          end_of_storage是指向当前分配的可使用空间的最后一个位置的下一个位置

    2、vector的迭代器

    vector维护的是一个连续空间,所以不论其元素的类型是什么,普通指针都可以作为vector的迭代器,可以满足vector迭代器所需要的所有操作行为,vector支持随机存取,而普通指针正有着这样的能力,所以vector的迭代器是一个Random Access Iterator

    3、vector如何实现动态数组

    当vector的预留空间无法满足时,vector就会扩张空间,将重新分配两倍的当前空间大小,将现有空间的所有对象移动到新的空间里,在释放掉原空间,如下图

    下面是vector的成员函数push_back的实现

     1 void push_back(const T& x) {
     2     //拥有预留空间    
     3     if (finish != end_of_storage) {
     4         std::allocator<T>().construct(finish, x);
     5         ++finish;
     6     } 
     7     //没有预留空间
     8     else
     9         inset_axu(end(), x);
    10 }

    可以看出动态分配空间技巧的实现落在了insert_axu()身上

     1 template<typename T>
     2 void Vector<T>::insert_axu(Vector::iterator position, const T &x) {
     3     //Vector拥有备用空间
     4     if (finish != end_of_storage) {                                                      
     5         std::allocator<T>().construct(finish, *(finish-1));
     6         ++finish;
     7         T x_copy = x;
     8         std::copy_backward(position, finish-2, finish-1);
     9         *position = x_copy;
    10 
    11     }
    12     //Vector没有备用空间
    13     else {                                                                               
    14         const size_type old_size = size();
    15         //当原来空间大小不为零时分配原来空间大小二倍的空间
    16         const size_type len = old_size == 0 ? 1 : 2 * old_size;                          
    17         iterator new_start = std::allocator<T>().allocate(len);
    18         iterator new_finish = new_start;
    19         try {
    20             //将原vector插入位置之前的内容拷贝到新vector
    21             new_finish = std::uninitialized_copy(start, position, new_start);
    22             //在新配置空间的finish位置设定要插入的对象
    23             std::allocator<T>().construct(new_finish, x);
    24             //更新新finish指向的位置
    25             ++new_finish;
    26             //将原vector插入位置之后的内容拷贝到新vector
    27             new_finish = std::uninitialized_copy(position, finish, new_finish);          
    28         }
    29         //若分配新空间时出现异常,则析构并释放新空间
    30         catch(...) {                                                                     
    31             auto iter = new_start;
    32             for (; iter != new_finish; ++iter)
    33                 std::allocator<T>().destroy(iter);
    34             std::allocator<T>().deallocate(new_start, len);
    35             throw;
    36         }
    37         //析构并释放原vector
    38         auto iter = begin();                                                             
    39         for (; iter != end(); ++iter)
    40             std::allocator<T>().destroy(iter);
    41         deallocate();
    42         //调整迭代器
    43         start = new_start;                                                               
    44         finish = new_finish;
    45         end_of_storage = new_finish + len;
    46 
    47     }
    48 }

    具体实现详见 https://github.com/anoov/myTinySTL/tree/master/myTinySTL

  • 相关阅读:
    android WebView 加载html5
    android 摄像头的使用
    android 传感器类 sensor
    关于java的一些东西
    android 网络连接管理机制
    利用Layout实现Button的不规则布局
    Android 推送通知指南(转载)
    android开发小问题随记(附1)
    ubuntu下搭建android开发环境(转载)
    北斗小辣椒双核升级攻略之一
  • 原文地址:https://www.cnblogs.com/swenwen/p/12526804.html
Copyright © 2011-2022 走看看