Fork me on GitHub

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

posted @ 2020-03-19 20:03  最后的战役aag  阅读(282)  评论(0编辑  收藏  举报