• c++ vector的模拟实现以及迭代器失效问题


    目录

    1.vector的模拟实现

    2.迭代器失效问题

    3.总结


    1.vector的模拟实现

    这里,我们使用三个指针来控制vector。

     用_start指向头,_finish指向最后一个元素的尾巴,_end指向最大容量。

    1. #include
    2. #include
    3. using namespace std;
    4. template<class T>
    5. class Vector
    6. {
    7. public:
    8. typedef T* iterator; //将原生指针模拟成迭代器
    9. typedef const T* const_iterator; //给一个const版本
    10. Vector()
    11. :_start(nullptr)
    12. , _finish(nullptr)
    13. , _end(nullptr)
    14. {}
    15. Vector(int n, const T& t = T())
    16. :_start(nullptr)
    17. , _finish(nullptr)
    18. , _end(nullptr)
    19. {
    20. reverse(n); //先开n个空间
    21. for (int i = 0; i < n; i++)
    22. {
    23. push_back(t); //插入这些值
    24. }
    25. }
    26. template<class iterator_begin, class iterator_end>
    27. Vector(iterator_begin begin, iterator_end end) //迭代器初始化版
    28. :_start(nullptr)
    29. , _finish(nullptr)
    30. , _end(nullptr)
    31. {
    32. while (begin != end)
    33. {
    34. push_back(*begin);
    35. begin++;
    36. }
    37. }
    38. void swap(Vector& v)
    39. {
    40. std::swap(_start, v._start);
    41. std::swap(_finish, v._finish);
    42. std::swap(_end, v._end);
    43. }
    44. Vector(Vector& v) //现代写法
    45. :_start(nullptr)
    46. , _finish(nullptr)
    47. , _end(nullptr)
    48. {
    49. Vector temp(v.begin(), v.end()); //先构造一个传入的拷贝
    50. swap(temp); //再交换
    51. }
    52. Vector& operator=(Vector t) //现代写法
    53. {
    54. swap(t); //因为t是传值,会发生拷贝。
    55. return *this;
    56. }
    57. iterator begin()
    58. {
    59. return _start;
    60. }
    61. iterator end()
    62. {
    63. return _finish;
    64. }
    65. const_iterator begin() const
    66. {
    67. return _start;
    68. }
    69. const_iterator end() const
    70. {
    71. return _finish;
    72. }
    73. ~Vector() //析构函数
    74. {
    75. delete[] _start;
    76. _start = _finish = _end;
    77. }
    78. size_t capacity()
    79. {
    80. return _end - _start;
    81. }
    82. size_t size()
    83. {
    84. return _finish - _start;
    85. }
    86. T& operator[](size_t pos)
    87. {
    88. assert(pos < size());
    89. return _start[pos];
    90. }
    91. void reverse(size_t n)
    92. {
    93. if (n > capacity())
    94. {
    95. int sz = size();
    96. T* temp = new T[n];
    97. if (_start) //保证非空
    98. {
    99. for (int i = 0; i < sz; i++)
    100. {
    101. temp[i] = _start[i];
    102. }
    103. delete _start;
    104. }
    105. _start = temp;
    106. _finish = _start + sz;
    107. _end = _start + n;
    108. }
    109. }
    110. void resize(size_t n, const T& val)
    111. {
    112. if(n > capacity())
    113. reverse(n);
    114. if (n > size())
    115. {
    116. while (_finish < _start + n)
    117. {
    118. *_finish = val;
    119. ++_finish;
    120. }
    121. }
    122. else
    123. {
    124. _finish = _start + n;
    125. }
    126. }
    127. void pop_back()
    128. {
    129. assert(_finish > _start);
    130. --_finish;
    131. }
    132. iterator insert(iterator pos, const T& val)
    133. {
    134. assert(pos >= _start);
    135. assert(pos <= _finish);
    136. if (_finish == _end) //满了
    137. {
    138. int len = pos - _start; //标记长度,不然下面找不到了。
    139. reverse(capacity() == 0 ? 4 : capacity() * 2);//非0开出2倍的空间
    140. pos = _start + len;
    141. }
    142. iterator cur = _finish-1; //因为finish会指向最后一个元素的尾部
    143. while (cur >= pos) //从最后一个位置向后移动
    144. {
    145. *(cur + 1) = *cur;
    146. --cur;
    147. }
    148. ++_finish;
    149. *pos = val;
    150. return pos;
    151. }
    152. void push_back(const T& t)
    153. {
    154. iterator temp = insert(end(), t); //复用插入
    155. }
    156. iterator erase(iterator pos) //返回删除位置下一个的迭代器
    157. {
    158. assert(pos >= _start);
    159. assert(pos <= _finish);
    160. iterator cur = pos + 1;
    161. while (cur < _finish)
    162. {
    163. *(cur - 1) = *cur; //挪动数据
    164. ++cur;
    165. }
    166. --_finish;
    167. return pos;
    168. }
    169. T& front()
    170. {
    171. assert(size() > 0);
    172. return *_start;
    173. }
    174. T& back()
    175. {
    176. assert(size() > 0);
    177. return *(_finish - 1);
    178. }
    179. private:
    180. iterator _start;
    181. iterator _finish;
    182. iterator _end;
    183. };

    需要注意的是:我们一般在拷贝构造或者扩容时会采用现代(托管+交换)的写法。

    reverse:会新开一个大小n的空间,再将原来的的值拿过来。

    拷贝构造:直接调用构造函数构造一个和传入的对象一样的实例,最后和this交换。

    与传统的原地处理不同的是,这种方式会创造一个临时变量来托管处理,最后再交换。


    2.迭代器失效问题

    对于vector迭代器的失效主要分为两种情况:

    a.扩容导致的野指针

    b.因为挪动数据导致迭代器失效

     以删除元素为例,删除2以后,pos就指向了3。pos指向内容发生了突然变化,这时也就发生了迭代器的失效,pos失去了作用。


    3.总结

    vector可以通过三个指针实现一个基本版。

    要特别注意迭代器失效问题,这是和野指针问题一样的严重程序设计问题。 

  • 相关阅读:
    JS 函数总结
    用Python分析《三国演义》中的人物关系网
    排序2:直接选择排序、堆排序、直接插入排序、希尔排序
    TcpServer::start都做了些什么
    《Windows API每日一练》4.4 绘制填充区域
    微服务架构——笔记(3)Eureka
    共享股东模式:创新方法助力连锁门店扩展业务并提高利润
    Linux基础概念--进程、子进程、进程组和会话
    NLP基本业务范围
    CSS 基础知识 选择器
  • 原文地址:https://blog.csdn.net/xiao_xiao21/article/details/128044600