当前位置:   article > 正文

【C++】vector的底层剖析以及模拟实现

【C++】vector的底层剖析以及模拟实现

一、vector的简单认识

        vector是表示可变大小数组的序列容器。 就像数组一样,vector也采用的连续存储空间来存储元素也就是意味着可以采用下标对vector的元素 进行访问,和数组一样高效。但是又不像数组,它的大小是可以动态改变的,而且它的大小会被容器自动处理。vector会分配一些额外的空间以适应可能的增长,因为存储空间比实际需要的存 储空间更大。不同的库采用不同的策略权衡空间的使用和重新分配。但是无论如何,重新分配都应该是对数增长的间隔大小,以至于在末尾插入一个元素的时候是在常数时间的复杂度完成的。与其它动态序列容器相比(deque, list and forward_list), vector在访问元素的时候更加高效,在末 尾添加和删除元素相对高效。对于其它不在末尾的删除和插入操作,效率更低。

二、vector的简单模拟实现

vector的底层我模仿库里面的实现方法,设计了三个指针:

  1. class vector
  2. {
  3. public:
  4. typedef T* iterator;
  5. private:
  6. iterator _start; // 指向数据块的开始
  7. iterator _finish; // 指向有效数据的尾
  8. iterator _endOfStorage; // 指向存储容量的尾
  9. }

以及正向迭代器,不可修改迭代器,各种构造函数,析构函数, reserve(预开辟出空间,字符串还是原来的大小(一般不缩容))resize(将vector设定为指定大小,字符串占满所开辟的空间)push_back(尾插)pop_back(尾删)insert(在pos位置上插入x,并返回pos位置的地址)erase(删除pos位置上的元素,并返回该位置的地址)。

注意事项:迭代器失效

        以reserve为例,当reserve开辟新空间时会释放原来的旧空间,导致_start,_finish都不是原来的_start,_finish,如果此时贸然对_start,_finish进行运算,很可能会导致程序崩溃。我的做法是先记录下原来vector的长度,再用_start加上记录下的长度,就能得到正确的_finish,具体实现见下面代码。

完整代码

  1. #pragma once
  2. #include <iostream>
  3. using namespace std;
  4. namespace sxb
  5. {
  6. template<class T>
  7. class vector
  8. {
  9. public:
  10. typedef T* iterator;
  11. private:
  12. iterator _start; // 指向数据块的开始
  13. iterator _finish; // 指向有效数据的尾
  14. iterator _endOfStorage; // 指向存储容量的尾
  15. public:
  16. // Vector的迭代器是一个原生指针
  17. typedef const T* const_iterator;
  18. iterator begin()
  19. {
  20. return _start;
  21. }
  22. iterator end()
  23. {
  24. return _finish;
  25. }
  26. const_iterator cbegin() const
  27. {
  28. return _start;
  29. }
  30. const_iterator cend() const
  31. {
  32. return _finish;
  33. }
  34. // construct and destroy
  35. vector() {}
  36. //构造一个长度为n,值为value的vector
  37. vector(int n, const T& value = T())
  38. {
  39. _start = new T[n+1];
  40. _finish = _start + n;
  41. _endOfStorage = _start + n;
  42. for (int i = 0; i < n; i++)
  43. {
  44. *(_start + i) = value;
  45. }
  46. }
  47. template<class InputIterator>
  48. //利用一段迭代器构造
  49. vector(InputIterator first, InputIterator last)
  50. {
  51. int len = 0;
  52. while (first != last)// 1 2 3 4 5
  53. {
  54. len++;
  55. first++;
  56. }
  57. len++;
  58. _start = new T[len+1];
  59. memcpy(_start, first, sizeof(T) * len);
  60. _finish = _start + len;
  61. _endOfStorage = _finish;
  62. }
  63. //利用已有的vector构造
  64. vector(const vector<T>& v)
  65. {
  66. _start = new T[v.size() + 1];
  67. memcpy(_start, v.cbegin(), sizeof(T) * v.size());
  68. _finish = _start + v.size();
  69. _endOfStorage = _finish;
  70. }
  71. //赋值构造
  72. vector<T>& operator= (vector<T> v)
  73. {
  74. vector(v);
  75. return *this;
  76. }
  77. ~vector()
  78. {
  79. delete[] _start;
  80. _finish = nullptr;
  81. _endOfStorage = nullptr;
  82. }
  83. // capacity
  84. size_t size() const
  85. {
  86. return _finish - _start;
  87. }
  88. size_t capacity() const
  89. {
  90. return _endOfStorage - _start;
  91. }
  92. void reserve(size_t n)
  93. {
  94. if (n > capacity())
  95. {
  96. T* tmp = new T[n + 1];
  97. //迭代器失效处理
  98. int oldnum = _finish - _start;
  99. memcpy(tmp, _start, sizeof(T) * (_finish - _start));
  100. delete[] _start;
  101. _start = tmp;
  102. _finish = _start + oldnum;
  103. _endOfStorage = _start + n;
  104. }
  105. }
  106. void resize(size_t n, const T& value = T())
  107. {
  108. if (n > capacity())
  109. {
  110. int oldnum = _finish - _start;
  111. reserve(n);
  112. while ((_start + oldnum) != _endOfStorage)
  113. {
  114. *(_start + oldnum) = value;
  115. oldnum++;
  116. }
  117. }
  118. else
  119. {
  120. _finish = _start + n;
  121. }
  122. }
  123. ///access///
  124. T& operator[](size_t pos)
  125. {
  126. return *(_start + pos);
  127. }
  128. const T& operator[](size_t pos)const
  129. {
  130. return *(_start + pos);
  131. }
  132. ///modify/
  133. void push_back(const T& x)
  134. {
  135. if (size() == capacity())
  136. {
  137. reserve(capacity() == 0 ? 4 : capacity() * 2);
  138. }
  139. _start[size()] = x;
  140. _finish++;
  141. }
  142. void pop_back()
  143. {
  144. _finish--;
  145. }
  146. void swap(vector<T>& v)
  147. {
  148. std::swap(_start, v._start);
  149. std::swap(_finish, v._finish);
  150. std::swap(_endOfStorage, v._endOfStorage);
  151. }
  152. //迭代器失效
  153. iterator insert(iterator pos, const T& x)
  154. {
  155. int len = 0;
  156. while (pos != _start)
  157. {
  158. len++;
  159. pos--;
  160. }
  161. if (size() == capacity())
  162. {
  163. reserve(capacity() == 0 ? 4 : capacity() * 2);
  164. }
  165. iterator endfinish = _finish;
  166. while (endfinish > _start + len)
  167. {
  168. *(endfinish) = *(endfinish - 1);
  169. endfinish--;
  170. }
  171. *endfinish = x;
  172. _finish++;
  173. return _start + len;
  174. }
  175. iterator erase(iterator pos)
  176. {
  177. iterator pos2 = pos;
  178. while (pos != _finish - 1)
  179. {
  180. *pos = *(pos + 1);
  181. pos++;
  182. }
  183. _finish--;
  184. return pos2;
  185. }
  186. };
  187. }

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/凡人多烦事01/article/detail/262119
推荐阅读
相关标签
  

闽ICP备14008679号