• C++【STL】【vector类的模拟实现】【迭代器失效问题】


    目录

    一、vector容器的基本结构

    二、vector容器的构造函数和析构函数

    三、迭代器

    四、返回容器中的相关参数

    五、交换函数

    六、拷贝构造

    1.拷贝指定范围的数据

    测试代码 

    2.拷贝构造 

    测试代码

    3.使用=拷贝构造

    七、扩容操作

    1.reserve扩容

    2.resize调整大小

    测试代码

    八、让我们的容器支持随机读写

    九、尾插尾删 

    1.尾插push_back

    2.尾删 pop_back

    3.将容器后面追加n个元素,元素为value 

    测试代码 

    十、随机位置插入和删除 

    1.随机位置插入insert

    2.随机位置擦除 

    3.清除函数clear 

    1)写法一:调用erase

    2)写法二:直接将_finish=_start

    测试代码

    ​编辑

    测试代码(clear)

    为什么要返回删除位置的下一个位置的迭代器? 

    十一、迭代器的失效问题

    问题的解决 

    测试代码

    十二、主程序代码汇总 

    十三、测试程序代码汇总

    调用测试程序

    测试程序

    十四、vector原码


    这里我们先将每一个小模块分别实现,然后最终的汇总代码和测试代码在后面

    一、vector容器的基本结构

    1. #pragma once
    2. #include
    3. #include
    4. namespace zhuyuan
    5. {
    6. template<class T>
    7. class vector
    8. {
    9. public:
    10. private:
    11. //_start是容器的初始位置
    12. iterator _start;
    13. //finish是最后一个数据的下一个位置
    14. iterator _finish;
    15. //_end_of_storage是我们整个vector的容量大小
    16. iterator _end_of_storage;
    17. };
    18. }

    二、vector容器的构造函数和析构函数

    1. //空参构造器
    2. vector()
    3. :_start(nullptr)
    4. ,_finish(nullptr)
    5. ,_end_of_storage(nullptr)
    6. {
    7. }
    8. //析构函数
    9. ~vector()
    10. {
    11. //析构的时候只要将整一个空间的首元素的地址传过去就可以了。
    12. delete[] _start;
    13. _start=_finish=_end_of_storage= nullptr;
    14. }

    三、迭代器

    其实连续的空间的迭代器可以用指针来实现

    1. typedef T* iterator;
    2. const typedef T* const_iterator;
    3. iterator begin()
    4. {
    5. return _start;
    6. }
    7. const iterator begin() const
    8. {
    9. return _start;
    10. }
    11. iterator end()
    12. {
    13. return _finish;
    14. }
    15. const iterator end() const
    16. {
    17. return _finish;
    18. }

    四、返回容器中的相关参数

    _end_of_storage表示的是容器中当前开辟的空间的最后位置的迭代器。

    _start表示的是当前的容器的首元素的位置

    _finish表示的当前容器中最后一个元素的下一个位置

    capacity表示的是当前容器的容量大小

    size表示的是当前容器中存储的元素个数

    1. size_t capacity() const
    2. {
    3. return _end_of_storage-_start;
    4. }
    5. size_t size() const
    6. {
    7. return _finish-_start;
    8. }

    五、交换函数

    对我们两个容器中的每一个成员变量都进行交换,交换可以直接调用我们的std中的交换函数。

    1. void swap(vector& v)
    2. {
    3. std::swap(_start, v._start);
    4. std::swap(_finish, v._finish);
    5. std::swap(_end_of_storage, v._endOfStorage);
    6. }

    六、拷贝构造

    1.拷贝指定范围的数据

    1. //将要拷贝的迭代器的范围传入
    2. vector(iterator first,iterator last)
    3. :_start(nullptr)
    4. ,_finish(nullptr)
    5. ,_end_of_storage(nullptr)
    6. {
    7. reserve(last-first+1);
    8. iterator it=begin();
    9. for(int i=0;i
    10. {
    11. *it=*(first+i);
    12. it++;
    13. }
    14. _finish=_start+(last-first);
    15. }

    测试代码 

    1. void myvector_test9()
    2. {
    3. vector<int> v1;
    4. v1.push_back(1);
    5. v1.push_back(2);
    6. vector<int> v2(v1.begin(),v1.end());
    7. cout<1]<
    8. }

    2.拷贝构造 

    1. vector(const vector& v)
    2. : _start(nullptr)
    3. , _finish(nullptr)
    4. , _end_of_storage(nullptr)
    5. {
    6. reserve(v.capacity());
    7. iterator it = begin();
    8. const_iterator vit = v.begin();
    9. while (vit != v.end())
    10. {
    11. *it++ = *vit++;
    12. }
    13. _finish = it;
    14. }

    测试代码

    1. void myvector_test8()
    2. {
    3. vector<int> v1;
    4. v1.push_back(1);
    5. v1.push_back(2);
    6. vector<int> v2(v1);
    7. vector<int>::iterator it=v2.begin();
    8. while(it!=v2.end())
    9. {
    10. cout<<*it<<" ";
    11. it++;
    12. }
    13. cout<
    14. }

    3.使用=拷贝构造

    这里我们可以采用和之前字符串中一样的老板式的写法

    由于编译器在将v传过来的时候会拷贝构造一个v,将这个v与我们当前的容器中的内容交换一下,我们的当前容器就完成拷贝了

    1. vector&operator =(vector v)
    2. {
    3. swap(v);
    4. return *this;
    5. }
    1. void myvector_test10()
    2. {
    3. vector<int> v1;
    4. v1.push_back(1);
    5. v1.push_back(2);
    6. vector<int> v2=v1;
    7. vector<int>::iterator it1=v1.begin();
    8. while(it1!=v1.end())
    9. {
    10. cout<<*it1<<" ";
    11. it1++;
    12. }
    13. cout<
    14. vector<int>::iterator it2=v2.begin();
    15. while(it2!=v2.end())
    16. {
    17. cout<<*it2<<" ";
    18. it2++;
    19. }
    20. cout<
    21. }

     

    七、扩容操作

    1.reserve扩容

    reserve如果传入的数据比当前的空间大小小的话是不会处理的。

    1. //开辟n个空间
    2. void reserve(size_t n)
    3. {
    4. if(n>capacity())
    5. {
    6. size_t sz=size();
    7. T*tmp=new T[n];
    8. if(_start)
    9. {
    10. memcpy(tmp,_start,sizeof(T)*size());
    11. delete[] _start;
    12. }
    13. _start=tmp;
    14. _finish=_start+sz;
    15. //由于上面的过程中我们将原先的_start给销毁了,新的_start变成了tmp
    16. //所以其size可能会发生变化,
    17. // _finish=_start+size();
    18. _end_of_storage=_start+n;
    19. }
    20. }

    2.resize调整大小

    1. //resize第一个参数是要调整到的大小,第二个参数是如果调整出来的大小大于了原来的数据用什么值填充
    2. void resize(size_t n,const T&value=T())
    3. {
    4. //1.如果n小于当前的size,则数据个数缩小到n
    5. if(n<=size())
    6. {
    7. _finish=_start+n;
    8. return;
    9. }
    10. //2.空间不够则增容
    11. if(n>capacity())
    12. {
    13. reserve(n);
    14. }
    15. //3.将size扩大到n
    16. iterator it=_finish;
    17. _finish=_start+n;
    18. while(it!=_finish)
    19. {
    20. *it=value;
    21. ++it;
    22. }
    23. }

    测试代码

    1. void myvector_test11()
    2. {
    3. vector<int> v1;
    4. v1.push_back(1);
    5. v1.push_back(2);
    6. v1.push_back(3);
    7. v1.push_back(4);
    8. vector<int>::iterator it1=v1.begin();
    9. while(it1!=v1.end())
    10. {
    11. cout<<*it1<<" ";
    12. it1++;
    13. }
    14. cout<
    15. vector<int>v2=v1;
    16. v1.resize(7,5);
    17. vector<int>::iterator it2=v1.begin();
    18. while(it2!=v1.end())
    19. {
    20. cout<<*it2<<" ";
    21. it2++;
    22. }
    23. cout<
    24. }

    八、让我们的容器支持随机读写

    我们分别需要提供const类型的和非const类型的。

    1. const T&operator [](size_t pos) const
    2. {
    3. assert(pos<size());
    4. return _start[pos];
    5. }
    6. T&operator [](size_t pos)
    7. {
    8. assert(pos<size());
    9. return _start[pos];
    10. }

    九、尾插尾删 

    1.尾插push_back

    尾插要注意扩容

    1. //使用泛型,输入的是T类型
    2. void push_back(const T&x)
    3. {
    4. if(_finish==_end_of_storage)
    5. {
    6. reserve(capacity()==0?4 :capacity()*2);
    7. }
    8. //finish是最后一个数据的下一个位置
    9. *_finish=x;
    10. ++_finish;
    11. }

    2.尾删 pop_back

    尾删我们需要先判断一下当前的容器还有没有元素

    1. void pop_back()
    2. {
    3. assert(_finish>_start);
    4. --_finish;
    5. }

    3.将容器后面追加n个元素,元素为value 

    1. vector v;
    2. // 如果下面的这个push_back不加const,就会报错,因为拷贝的这个字符串具有隐式类型转换
    3. // 期间会生成一个中间的临时变量,而这个临时变量具有常性。如果不加const会发生权限的扩大。
    4. // v.push_back("xxxx")
    5. vector(size_t n, const T& value = T())
    6. : _start(nullptr)
    7. , _finish(nullptr)
    8. , _end_of_storage(nullptr)
    9. {
    10. reserve(n);
    11. while (n--)
    12. {
    13. push_back(value);
    14. }
    15. }

    测试代码 

    1. //使用迭代器遍历容器
    2. void Func(const vector<int>&v)
    3. {
    4. vector<int>::const_iterator it=v.begin();
    5. while(it!=v.end())
    6. {
    7. cout<<*it<<" ";
    8. ++it;
    9. }
    10. cout<
    11. }
    12. void myvector_test1()
    13. {
    14. vector<int> v;
    15. v.push_back(1);
    16. v.push_back(2);
    17. v.push_back(3);
    18. v.push_back(4);
    19. v.push_back(5);
    20. //使用随机读取的方式遍历
    21. for(size_t i=0;isize();++i)
    22. {
    23. cout<" ";
    24. }
    25. cout<
    26. vector<int>::iterator it=v.begin();
    27. while(it!=v.end())
    28. {
    29. cout<<*it<<" ";
    30. ++it;
    31. }
    32. cout<
    33. //使用范围for的形式遍历容器
    34. //有了迭代器就支持范围for,也就是调用我们的v.begin(),v.end()来执行相关的操作
    35. //const的话就走const的迭代器,
    36. for(auto e:v)
    37. {
    38. cout<" ";
    39. }
    40. v.pop_back();
    41. cout<
    42. Func(v);
    43. }

    十、随机位置插入和删除 

    1.随机位置插入insert

    迭代器失效就是当我们尾插数据的时候,如果发生了扩容,原来的地址空间可能就被转换到了一块更大的空间,所以我们迭代器的指针就失效了。所以我们如果发生了扩容就要及时更新指针。

    1. // void insert(iterator &pos ,const T& x)
    2. void insert(iterator pos ,const T& x)
    3. {
    4. assert(pos>=_start);
    5. //等于finish就是尾插
    6. assert(pos<=_finish);
    7. if(_finish==_end_of_storage)
    8. {
    9. //如果发生了扩容就要重新调整我们的pos指针的位置,不然就会发生迭代器失效的问题
    10. size_t len=pos-_start;
    11. reserve(capacity()==0? 4:capacity()*2);
    12. //形参是实参的拷贝,并不会真正去改变我们外部的pos
    13. //仅仅只能保证我们下面的pos使用是正常的
    14. pos=_start+len;
    15. }
    16. //挪动数据
    17. iterator end=_finish -1;
    18. while(end>=pos)
    19. {
    20. *(end+1)=*end;
    21. --end;
    22. }
    23. *pos=x;
    24. ++_finish;
    25. }

    2.随机位置擦除 

    随机位置擦除的话可以使用缩容来优化我们过大的空间,但是这是一种时间换空间的做法,一般不用做。可以将下面代码中的缩容那部分注释掉。

    1. //stl规定erase返回删除位置的下一个位置迭代器
    2. iterator erase(iterator pos)
    3. {
    4. assert(pos>=_start);
    5. assert(pos<_finish);
    6. iterator begin=pos+1;
    7. //将当前位置不断挪动到前一个位置
    8. while(begin<_finish)
    9. {
    10. *(begin-1)=*begin;
    11. ++begin;
    12. }
    13. --_finish;
    14. if(size()<capacity()/2)
    15. {
    16. //缩容,以时间换空间。
    17. _end_of_storage=_start+capacity()/2;
    18. }
    19. return pos;
    20. }

    3.清除函数clear 

    1)写法一:调用erase

    1. void clear()
    2. {
    3. while(_finish!=_start)
    4. {
    5. erase(_start);
    6. }
    7. }

    2)写法二:直接将_finish=_start

    1. void clear()
    2. {
    3. _finish = _start;
    4. }

    测试代码

    1. void myvector_test3()
    2. {
    3. vector<int> v;
    4. v.push_back(1);
    5. v.push_back(2);
    6. v.push_back(3);
    7. v.push_back(4);
    8. // v.push_back(5);
    9. for(size_t i=0;isize();++i)
    10. {
    11. cout<" ";
    12. }
    13. cout<
    14. v.erase(v.begin());
    15. for(size_t i=0;isize();++i)
    16. {
    17. cout<" ";
    18. }
    19. cout<
    20. }

    测试代码(clear)

    1. void myvector_test13()
    2. {
    3. vector<int> v1;
    4. v1.push_back(1);
    5. v1.push_back(2);
    6. v1.push_back(3);
    7. vector<int>::iterator it=v1.begin();
    8. while(it!=v1.end())
    9. {
    10. cout<<*it<<" ";
    11. it++;
    12. }
    13. cout<
    14. v1.clear();
    15. vector<int>::iterator it2=v1.begin();
    16. while(it2!=v1.end())
    17. {
    18. cout<<*it2<<" ";
    19. it2++;
    20. }
    21. cout<
    22. }

    为什么要返回删除位置的下一个位置的迭代器? 

    观察下面几个代码的变化和问题

    1. void myvector_test4()
    2. {
    3. //正常运行
    4. vector<int> v;
    5. v.push_back(1);
    6. v.push_back(2);
    7. v.push_back(3);
    8. v.push_back(4);
    9. v.push_back(5);
    10. //要求删除所有的偶数
    11. auto it=v.begin();
    12. while(it!=v.end())
    13. {
    14. if(*it%2==0)
    15. {
    16. v.erase(it);
    17. }
    18. ++it;
    19. }
    20. for(size_t i=0;isize();++i)
    21. {
    22. cout<" ";
    23. }
    24. cout<
    25. }

    相比于上面 这里我们少push_back了5

    1. //崩溃
    2. void myvector_test5()
    3. {
    4. vector<int> v;
    5. v.push_back(1);
    6. v.push_back(2);
    7. v.push_back(3);
    8. v.push_back(4);
    9. //要求删除所有的偶数
    10. auto it=v.begin();
    11. while(it!=v.end())
    12. {
    13. if(*it%2==0)
    14. {
    15. v.erase(it);
    16. }
    17. ++it;
    18. }
    19. for(size_t i=0;isize();++i)
    20. {
    21. cout<" ";
    22. }
    23. cout<
    24. }

     ​​​​​​​

    1. //4删不掉
    2. void myvector_test6()
    3. {
    4. //正常运行
    5. vector<int> v;
    6. v.push_back(1);
    7. v.push_back(2);
    8. v.push_back(4);
    9. v.push_back(3);
    10. v.push_back(4);
    11. v.push_back(5);
    12. v.push_back(5);
    13. //要求删除所有的偶数
    14. auto it=v.begin();
    15. while(it!=v.end())
    16. {
    17. if(*it%2==0)
    18. {
    19. v.erase(it);
    20. }
    21. ++it;
    22. }
    23. for(size_t i=0;isize();++i)
    24. {
    25. cout<" ";
    26. }
    27. cout<
    28. }

    这里的4我们没删掉 

     正确的使用方式是我们在erase的时候就要同步更新我们的pos

    1. void myvector_test7()
    2. {
    3. //正常运行
    4. vector<int> v;
    5. v.push_back(1);
    6. v.push_back(2);
    7. v.push_back(4);
    8. v.push_back(3);
    9. v.push_back(4);
    10. v.push_back(5);
    11. //要求删除所有的偶数
    12. auto it=v.begin();
    13. while(it!=v.end())
    14. {
    15. if(*it%2==0)
    16. {
    17. //同步更新我们的it
    18. //如果删除了某个数据,it迭代器就不要继续往后走了
    19. //因为后面的数据会移动上来,it迭代器当前指向位置并没有检查过
    20. it=v.erase(it);
    21. }
    22. else
    23. {
    24. ++it;
    25. }
    26. }
    27. for(size_t i=0;isize();++i)
    28. {
    29. cout<" ";
    30. }
    31. cout<
    32. }
    33. //结论:insert/erase pos位置,不要直接访问pos。
    34. // 一定要更新,直接访问,可能会出现各种出乎意料的结果
    35. //这就是pos所谓的迭代器失效。
    36. //认为pos失效,不要访问。
    37. //结果不同的底层实现可能不一样。

    十一、迭代器的失效问题

    迭代器失效就是当我们尾插数据的时候,如果发生了扩容,原来的地址空间可能就被转换到了一块更大的空间,所以我们迭代器的指针就失效了。

    1. //迭代器失效问题
    2. void myvector_test2()
    3. {
    4. vector<int> v;
    5. v.push_back(1);
    6. v.push_back(2);
    7. v.push_back(3);
    8. v.push_back(4);
    9. // v.push_back(5);
    10. for(size_t i=0;isize();++i)
    11. {
    12. cout<" ";
    13. }
    14. cout<
    15. //这里由于我们之前扩容的写法(在上面的push_back中看),是初始开辟四个,然后超出的话空间直接乘以两倍,所以我们在第五个数据插入的时候就会发生扩容
    16. //在vector发生扩容的时候,我们的迭代器的指针就失效了,就会发生迭代器失效的问题
    17. auto p=find(v.begin(),v.end(),3);
    18. if(p!=v.end())
    19. {
    20. //在p位置插入数据以后,不要访问p,因为p可能失效
    21. v.insert(p,30);
    22. cout<<*p<
    23. //因为上面的insert30的时候p的指针已经失效了,所以会报错
    24. v.insert(p,40);
    25. }
    26. vector<int>::iterator it=v.begin();
    27. while(it!=v.end())
    28. {
    29. cout<<*it<<" ";
    30. ++it;
    31. }
    32. //如果上面的insert加了引用,下面这个代码就会报错。
    33. //传值返回的都是数据的临时拷贝,这个拷贝具有常性,不能被修改,会报错
    34. v.insert(v.begin(),1);
    35. }

    问题的解决 

     我们同样可以仿照erase中的写法,将我们insert函数中当前的扩容之后的对应位置的迭代器返回,然后及时同步迭代器,从而解决这个问题。

    1. iterator insert(iterator pos ,const T& x)
    2. {
    3. assert(pos>=_start);
    4. //等于finish就是尾插
    5. assert(pos<=_finish);
    6. if(_finish==_end_of_storage)
    7. {
    8. //如果发生了扩容就要重新调整我们的pos指针的位置,不然就会发生迭代器失效的问题
    9. size_t len=pos-_start;
    10. reserve(capacity()==0? 4:capacity()*2);
    11. //形参是实参的拷贝,并不会真正去改变pos
    12. pos=_start+len;
    13. }
    14. //挪动数据
    15. iterator end=_finish -1;
    16. while(end>=pos)
    17. {
    18. *(end+1)=*end;
    19. --end;
    20. }
    21. *pos=x;
    22. ++_finish;
    23. return pos;
    24. }

    测试代码

    1. //迭代器失效问题
    2. void myvector_test12()
    3. {
    4. vector<int> v;
    5. v.push_back(1);
    6. v.push_back(2);
    7. v.push_back(3);
    8. v.push_back(4);
    9. // v.push_back(5);
    10. for(size_t i=0;isize();++i)
    11. {
    12. cout<" ";
    13. }
    14. cout<
    15. //在vector发生扩容的时候,我们的迭代器的指针就失效了,就会发生迭代器失效的问题
    16. auto p=find(v.begin(),v.end(),3);
    17. if(p!=v.end())
    18. {
    19. //在p位置插入数据以后,及时同步指针
    20. p=v.insert(p,30);
    21. for(size_t i=0;isize();++i)
    22. {
    23. cout<" ";
    24. }
    25. cout<
    26. p=v.insert(p,40);
    27. }
    28. vector<int>::iterator it=v.begin();
    29. while(it!=v.end())
    30. {
    31. cout<<*it<<" ";
    32. ++it;
    33. }
    34. }

    十二、主程序代码汇总 

    1. #ifndef VECTORTEST_MYVECTOR_H
    2. #define VECTORTEST_MYVECTOR_H
    3. #pragma once
    4. #include
    5. #include
    6. namespace zhuyuan
    7. {
    8. template<class T>
    9. class vector
    10. {
    11. public:
    12. typedef T* iterator;
    13. const typedef T* const_iterator;
    14. iterator begin()
    15. {
    16. return _start;
    17. }
    18. const iterator begin() const
    19. {
    20. return _start;
    21. }
    22. iterator end()
    23. {
    24. return _finish;
    25. }
    26. const iterator end() const
    27. {
    28. return _finish;
    29. }
    30. vector()
    31. :_start(nullptr)
    32. ,_finish(nullptr)
    33. ,_end_of_storage(nullptr)
    34. {
    35. }
    36. ~vector()
    37. {
    38. delete[] _start;
    39. _start=_finish=_end_of_storage= nullptr;
    40. }
    41. size_t capacity() const
    42. {
    43. return _end_of_storage-_start;
    44. }
    45. size_t size() const
    46. {
    47. return _finish-_start;
    48. }
    49. // vector v;
    50. // 如果下面的这个push_back不加const,就会报错,因为拷贝的这个字符串具有隐式类型转换
    51. // 期间会生成一个中间的临时变量,而这个临时变量具有常性。如果不加const会发生权限的扩大。
    52. // v.push_back("xxxx")
    53. vector(size_t n, const T& value = T())
    54. : _start(nullptr)
    55. , _finish(nullptr)
    56. , _end_of_storage(nullptr)
    57. {
    58. reserve(n);
    59. while (n--)
    60. {
    61. push_back(value);
    62. }
    63. }
    64. vector(iterator first,iterator last)
    65. :_start(nullptr)
    66. ,_finish(nullptr)
    67. ,_end_of_storage(nullptr)
    68. {
    69. reserve(last-first+1);
    70. iterator it=begin();
    71. for(int i=0;i
    72. {
    73. *it=*(first+i);
    74. it++;
    75. }
    76. _finish=_start+(last-first);
    77. }
    78. vector(const vector& v)
    79. : _start(nullptr)
    80. , _finish(nullptr)
    81. , _end_of_storage(nullptr)
    82. {
    83. reserve(v.capacity());
    84. iterator it = begin();
    85. const_iterator vit = v.begin();
    86. while (vit != v.end())
    87. {
    88. *it++ = *vit++;
    89. }
    90. _finish = it;
    91. }
    92. vector&operator =(vector v)
    93. {
    94. swap(v);
    95. return *this;
    96. }
    97. void swap(vector& v)
    98. {
    99. std::swap(_start, v._start);
    100. std::swap(_finish, v._finish);
    101. std::swap(_end_of_storage, v._endOfStorage);
    102. }
    103. //开辟n个空间
    104. void reserve(size_t n)
    105. {
    106. if(n>capacity())
    107. {
    108. size_t sz=size();
    109. T*tmp=new T[n];
    110. if(_start)
    111. {
    112. memcpy(tmp,_start,sizeof(T)*size());
    113. delete[] _start;
    114. }
    115. _start=tmp;
    116. _finish=_start+sz;
    117. //由于上面的过程中我们将原先的_start给销毁了,新的_start变成了tmp
    118. //所以其size可能会发生变化,
    119. // _finish=_start+size();
    120. _end_of_storage=_start+n;
    121. }
    122. }
    123. //resize第一个参数是要调整到的大小,第二个参数是如果调整出来的大小大于了原来的数据用什么值填充
    124. void resize(size_t n,const T&value=T())
    125. {
    126. //1.如果n小于当前的size,则数据个数缩小到n
    127. if(n<=size())
    128. {
    129. _finish=_start+n;
    130. return;
    131. }
    132. //2.空间不够则增容
    133. if(n>capacity())
    134. {
    135. reserve(n);
    136. }
    137. //3.将size扩大到n
    138. iterator it=_finish;
    139. _finish=_start+n;
    140. while(it!=_finish)
    141. {
    142. *it=value;
    143. ++it;
    144. }
    145. }
    146. const T&operator [](size_t pos) const
    147. {
    148. assert(pos<size());
    149. return _start[pos];
    150. }
    151. T&operator [](size_t pos)
    152. {
    153. assert(pos<size());
    154. return _start[pos];
    155. }
    156. //使用泛型,输入的是T类型
    157. void push_back(const T&x)
    158. {
    159. if(_finish==_end_of_storage)
    160. {
    161. reserve(capacity()==0?4 :capacity()*2);
    162. }
    163. //finish是最后一个数据的下一个位置
    164. *_finish=x;
    165. ++_finish;
    166. }
    167. void pop_back()
    168. {
    169. assert(_finish>_start);
    170. --_finish;
    171. }
    172. // void insert(iterator &pos ,const T& x)
    173. iterator insert(iterator pos ,const T& x)
    174. {
    175. assert(pos>=_start);
    176. //等于finish就是尾插
    177. assert(pos<=_finish);
    178. if(_finish==_end_of_storage)
    179. {
    180. //如果发生了扩容就要重新调整我们的pos指针的位置,不然就会发生迭代器失效的问题
    181. size_t len=pos-_start;
    182. reserve(capacity()==0? 4:capacity()*2);
    183. //形参是实参的拷贝,并不会真正去改变pos
    184. pos=_start+len;
    185. }
    186. //挪动数据
    187. iterator end=_finish -1;
    188. while(end>=pos)
    189. {
    190. *(end+1)=*end;
    191. --end;
    192. }
    193. *pos=x;
    194. ++_finish;
    195. return pos;
    196. }
    197. //stl规定erase返回删除位置的下一个位置迭代器
    198. iterator erase(iterator pos)
    199. {
    200. assert(pos>=_start);
    201. assert(pos<_finish);
    202. iterator begin=pos+1;
    203. //将当前位置不断挪动到前一个位置
    204. while(begin<_finish)
    205. {
    206. *(begin-1)=*begin;
    207. ++begin;
    208. }
    209. --_finish;
    210. if(size()<capacity()/2)
    211. {
    212. //缩容,以时间换空间。
    213. _end_of_storage=_start+capacity()/2;
    214. }
    215. return pos;
    216. }
    217. private:
    218. iterator _start;
    219. //finish是最后一个数据的下一个位置
    220. iterator _finish;
    221. //_end_of_storage是我们整个vector的容量大小
    222. iterator _end_of_storage;
    223. };
    224. }
    225. #endif //VECTORTEST_MYVECTOR_H

    十三、测试程序代码汇总

    调用测试程序

    1. using namespace std;
    2. #include "myvector.h"
    3. int main()
    4. {
    5. try
    6. {
    7. zhuyuan::myvector_test1();
    8. }
    9. catch(std::exception&e)
    10. {
    11. std::cout<what()<
    12. }
    13. }

    测试程序

    1. void Func(const vector<int>&v)
    2. {
    3. vector<int>::const_iterator it=v.begin();
    4. while(it!=v.end())
    5. {
    6. cout<<*it<<" ";
    7. ++it;
    8. }
    9. cout<
    10. }
    11. void myvector_test1()
    12. {
    13. vector<int> v;
    14. v.push_back(1);
    15. v.push_back(2);
    16. v.push_back(3);
    17. v.push_back(4);
    18. v.push_back(5);
    19. for(size_t i=0;isize();++i)
    20. {
    21. cout<" ";
    22. }
    23. cout<
    24. vector<int>::iterator it=v.begin();
    25. while(it!=v.end())
    26. {
    27. cout<<*it<<" ";
    28. ++it;
    29. }
    30. cout<
    31. //有了迭代器就支持范围for,也就是调用我们的v.begin(),v.end()来执行相关的操作
    32. //const的话就走const的迭代器,
    33. for(auto e:v)
    34. {
    35. cout<" ";
    36. }
    37. v.pop_back();
    38. cout<
    39. Func(v);
    40. }
    41. //迭代器失效问题
    42. void myvector_test2()
    43. {
    44. vector<int> v;
    45. v.push_back(1);
    46. v.push_back(2);
    47. v.push_back(3);
    48. v.push_back(4);
    49. // v.push_back(5);
    50. for(size_t i=0;isize();++i)
    51. {
    52. cout<" ";
    53. }
    54. cout<
    55. //在vector发生扩容的时候,我们的迭代器的指针就失效了,就会发生迭代器失效的问题
    56. auto p=find(v.begin(),v.end(),3);
    57. if(p!=v.end())
    58. {
    59. //在p位置插入数据以后,不要访问p,因为p可能失效
    60. v.insert(p,30);
    61. cout<<*p<
    62. v.insert(p,40);
    63. }
    64. vector<int>::iterator it=v.begin();
    65. while(it!=v.end())
    66. {
    67. cout<<*it<<" ";
    68. ++it;
    69. }
    70. //如果上面的insert加了引用,下面这个代码就会报错。
    71. //传值返回的都是数据的临时拷贝,这个拷贝具有常性,不能被修改,会报错
    72. v.insert(v.begin(),1);
    73. }
    74. void myvector_test3()
    75. {
    76. vector<int> v;
    77. v.push_back(1);
    78. v.push_back(2);
    79. v.push_back(3);
    80. v.push_back(4);
    81. // v.push_back(5);
    82. for(size_t i=0;isize();++i)
    83. {
    84. cout<" ";
    85. }
    86. cout<
    87. v.erase(v.begin());
    88. for(size_t i=0;isize();++i)
    89. {
    90. cout<" ";
    91. }
    92. cout<
    93. }
    94. void myvector_test4()
    95. {
    96. //正常运行
    97. vector<int> v;
    98. v.push_back(1);
    99. v.push_back(2);
    100. v.push_back(3);
    101. v.push_back(4);
    102. v.push_back(5);
    103. //要求删除所有的偶数
    104. auto it=v.begin();
    105. while(it!=v.end())
    106. {
    107. if(*it%2==0)
    108. {
    109. v.erase(it);
    110. }
    111. ++it;
    112. }
    113. for(size_t i=0;isize();++i)
    114. {
    115. cout<" ";
    116. }
    117. cout<
    118. }
    119. //崩溃
    120. void myvector_test5()
    121. {
    122. vector<int> v;
    123. v.push_back(1);
    124. v.push_back(2);
    125. v.push_back(3);
    126. v.push_back(4);
    127. //要求删除所有的偶数
    128. auto it=v.begin();
    129. while(it!=v.end())
    130. {
    131. cout<<"it"<<*it<
    132. // cout<<*it<
    133. if(*it%2==0)
    134. {
    135. cout<<"end()"<end()-v.begin()<
    136. v.erase(it);
    137. }
    138. ++it;
    139. }
    140. for(size_t i=0;isize();++i)
    141. {
    142. cout<" ";
    143. }
    144. cout<
    145. }
    146. //4删不掉
    147. void myvector_test6()
    148. {
    149. //正常运行
    150. vector<int> v;
    151. v.push_back(1);
    152. v.push_back(2);
    153. v.push_back(4);
    154. v.push_back(3);
    155. v.push_back(4);
    156. v.push_back(5);
    157. v.push_back(5);
    158. //要求删除所有的偶数
    159. auto it=v.begin();
    160. while(it!=v.end())
    161. {
    162. if(*it%2==0)
    163. {
    164. v.erase(it);
    165. }
    166. ++it;
    167. }
    168. for(size_t i=0;isize();++i)
    169. {
    170. cout<" ";
    171. }
    172. cout<
    173. }
    174. void myvector_test7()
    175. {
    176. //正常运行
    177. vector<int> v;
    178. v.push_back(1);
    179. v.push_back(2);
    180. v.push_back(4);
    181. v.push_back(3);
    182. v.push_back(4);
    183. v.push_back(5);
    184. //要求删除所有的偶数
    185. auto it=v.begin();
    186. while(it!=v.end())
    187. {
    188. if(*it%2==0)
    189. {
    190. it=v.erase(it);
    191. }
    192. else
    193. {
    194. ++it;
    195. }
    196. }
    197. for(size_t i=0;isize();++i)
    198. {
    199. cout<" ";
    200. }
    201. cout<
    202. }
    203. //结论:insert/erase pos位置,不要直接访问pos。
    204. // 一定要更新,直接访问,可能会出现各种出乎意料的结果
    205. //这就是pos所谓的迭代器失效。
    206. //认为pos失效,不要访问。
    207. //结果不同的底层实现可能不一样。
    208. void myvector_test8()
    209. {
    210. vector<int> v1;
    211. v1.push_back(1);
    212. v1.push_back(2);
    213. vector<int> v2(v1);
    214. vector<int>::iterator it=v2.begin();
    215. while(it!=v2.end())
    216. {
    217. cout<<*it<<" ";
    218. it++;
    219. }
    220. cout<
    221. }
    222. void myvector_test9()
    223. {
    224. vector<int> v1;
    225. v1.push_back(1);
    226. v1.push_back(2);
    227. vector<int> v2(v1.begin(),v1.end());
    228. cout<1]<
    229. }
    230. void myvector_test10()
    231. {
    232. vector<int> v1;
    233. v1.push_back(1);
    234. v1.push_back(2);
    235. vector<int> v2=v1;
    236. vector<int>::iterator it1=v1.begin();
    237. while(it1!=v1.end())
    238. {
    239. cout<<*it1<<" ";
    240. it1++;
    241. }
    242. cout<
    243. vector<int>::iterator it2=v2.begin();
    244. while(it2!=v2.end())
    245. {
    246. cout<<*it2<<" ";
    247. it2++;
    248. }
    249. cout<
    250. }
    251. void myvector_test11()
    252. {
    253. vector<int> v1;
    254. v1.push_back(1);
    255. v1.push_back(2);
    256. v1.push_back(3);
    257. v1.push_back(4);
    258. vector<int>::iterator it1=v1.begin();
    259. while(it1!=v1.end())
    260. {
    261. cout<<*it1<<" ";
    262. it1++;
    263. }
    264. cout<
    265. vector<int>v2=v1;
    266. v1.resize(7,5);
    267. vector<int>::iterator it2=v1.begin();
    268. while(it2!=v1.end())
    269. {
    270. cout<<*it2<<" ";
    271. it2++;
    272. }
    273. cout<
    274. }
    275. //迭代器失效问题
    276. void myvector_test12()
    277. {
    278. vector<int> v;
    279. v.push_back(1);
    280. v.push_back(2);
    281. v.push_back(3);
    282. v.push_back(4);
    283. // v.push_back(5);
    284. for(size_t i=0;isize();++i)
    285. {
    286. cout<" ";
    287. }
    288. cout<
    289. //在vector发生扩容的时候,我们的迭代器的指针就失效了,就会发生迭代器失效的问题
    290. auto p=find(v.begin(),v.end(),3);
    291. if(p!=v.end())
    292. {
    293. //在p位置插入数据以后,及时同步指针
    294. p=v.insert(p,30);
    295. for(size_t i=0;isize();++i)
    296. {
    297. cout<" ";
    298. }
    299. cout<
    300. p=v.insert(p,40);
    301. }
    302. vector<int>::iterator it=v.begin();
    303. while(it!=v.end())
    304. {
    305. cout<<*it<<" ";
    306. ++it;
    307. }
    308. }

    十四、vector原码

    可以对照原码查看我们上面的模拟实现代码

    1. /*
    2. *
    3. * Copyright (c) 1994
    4. * Hewlett-Packard Company
    5. *
    6. * Permission to use, copy, modify, distribute and sell this software
    7. * and its documentation for any purpose is hereby granted without fee,
    8. * provided that the above copyright notice appear in all copies and
    9. * that both that copyright notice and this permission notice appear
    10. * in supporting documentation. Hewlett-Packard Company makes no
    11. * representations about the suitability of this software for any
    12. * purpose. It is provided "as is" without express or implied warranty.
    13. *
    14. *
    15. * Copyright (c) 1996
    16. * Silicon Graphics Computer Systems, Inc.
    17. *
    18. * Permission to use, copy, modify, distribute and sell this software
    19. * and its documentation for any purpose is hereby granted without fee,
    20. * provided that the above copyright notice appear in all copies and
    21. * that both that copyright notice and this permission notice appear
    22. * in supporting documentation. Silicon Graphics makes no
    23. * representations about the suitability of this software for any
    24. * purpose. It is provided "as is" without express or implied warranty.
    25. */
    26. /* NOTE: This is an internal header file, included by other STL headers.
    27. * You should not attempt to use it directly.
    28. */
    29. #ifndef __SGI_STL_INTERNAL_VECTOR_H
    30. #define __SGI_STL_INTERNAL_VECTOR_H
    31. __STL_BEGIN_NAMESPACE
    32. #if defined(__sgi) && !defined(__GNUC__) && (_MIPS_SIM != _MIPS_SIM_ABI32)
    33. #pragma set woff 1174
    34. #endif
    35. template <class T, class Alloc = alloc>
    36. class vector {
    37. public:
    38. typedef T value_type;
    39. typedef value_type* pointer;
    40. typedef const value_type* const_pointer;
    41. typedef value_type* iterator;
    42. typedef const value_type* const_iterator;
    43. typedef value_type& reference;
    44. typedef const value_type& const_reference;
    45. typedef size_t size_type;
    46. typedef ptrdiff_t difference_type;
    47. #ifdef __STL_CLASS_PARTIAL_SPECIALIZATION
    48. typedef reverse_iterator const_reverse_iterator;
    49. typedef reverse_iterator reverse_iterator;
    50. #else /* __STL_CLASS_PARTIAL_SPECIALIZATION */
    51. typedef reverse_iterator
    52. difference_type> const_reverse_iterator;
    53. typedef reverse_iterator
    54. reverse_iterator;
    55. #endif /* __STL_CLASS_PARTIAL_SPECIALIZATION */
    56. protected:
    57. typedef simple_alloc data_allocator;
    58. iterator start;
    59. iterator finish;
    60. iterator end_of_storage;
    61. void insert_aux(iterator position, const T& x);
    62. void deallocate() {
    63. if (start) data_allocator::deallocate(start, end_of_storage - start);
    64. }
    65. void fill_initialize(size_type n, const T& value) {
    66. start = allocate_and_fill(n, value);
    67. finish = start + n;
    68. end_of_storage = finish;
    69. }
    70. public:
    71. iterator begin() { return start; }
    72. const_iterator begin() const { return start; }
    73. iterator end() { return finish; }
    74. const_iterator end() const { return finish; }
    75. reverse_iterator rbegin() { return reverse_iterator(end()); }
    76. const_reverse_iterator rbegin() const {
    77. return const_reverse_iterator(end());
    78. }
    79. reverse_iterator rend() { return reverse_iterator(begin()); }
    80. const_reverse_iterator rend() const {
    81. return const_reverse_iterator(begin());
    82. }
    83. size_type size() const { return size_type(end() - begin()); }
    84. size_type max_size() const { return size_type(-1) / sizeof(T); }
    85. size_type capacity() const { return size_type(end_of_storage - begin()); }
    86. bool empty() const { return begin() == end(); }
    87. reference operator[](size_type n) { return *(begin() + n); }
    88. const_reference operator[](size_type n) const { return *(begin() + n); }
    89. vector() : start(0), finish(0), end_of_storage(0) {}
    90. vector(size_type n, const T& value) { fill_initialize(n, value); }
    91. vector(int n, const T& value) { fill_initialize(n, value); }
    92. vector(long n, const T& value) { fill_initialize(n, value); }
    93. explicit vector(size_type n) { fill_initialize(n, T()); }
    94. vector(const vector& x) {
    95. start = allocate_and_copy(x.end() - x.begin(), x.begin(), x.end());
    96. finish = start + (x.end() - x.begin());
    97. end_of_storage = finish;
    98. }
    99. #ifdef __STL_MEMBER_TEMPLATES
    100. template <class InputIterator>
    101. vector(InputIterator first, InputIterator last) :
    102. start(0), finish(0), end_of_storage(0)
    103. {
    104. range_initialize(first, last, iterator_category(first));
    105. }
    106. #else /* __STL_MEMBER_TEMPLATES */
    107. vector(const_iterator first, const_iterator last) {
    108. size_type n = 0;
    109. distance(first, last, n);
    110. start = allocate_and_copy(n, first, last);
    111. finish = start + n;
    112. end_of_storage = finish;
    113. }
    114. #endif /* __STL_MEMBER_TEMPLATES */
    115. ~vector() {
    116. destroy(start, finish);
    117. deallocate();
    118. }
    119. vector& operator=(const vector& x);
    120. void reserve(size_type n) {
    121. if (capacity() < n) {
    122. const size_type old_size = size();
    123. iterator tmp = allocate_and_copy(n, start, finish);
    124. destroy(start, finish);
    125. deallocate();
    126. start = tmp;
    127. finish = tmp + old_size;
    128. end_of_storage = start + n;
    129. }
    130. }
    131. reference front() { return *begin(); }
    132. const_reference front() const { return *begin(); }
    133. reference back() { return *(end() - 1); }
    134. const_reference back() const { return *(end() - 1); }
    135. void push_back(const T& x) {
    136. if (finish != end_of_storage) {
    137. construct(finish, x);
    138. ++finish;
    139. }
    140. else
    141. insert_aux(end(), x);
    142. }
    143. void swap(vector& x) {
    144. __STD::swap(start, x.start);
    145. __STD::swap(finish, x.finish);
    146. __STD::swap(end_of_storage, x.end_of_storage);
    147. }
    148. iterator insert(iterator position, const T& x) {
    149. size_type n = position - begin();
    150. if (finish != end_of_storage && position == end()) {
    151. construct(finish, x);
    152. ++finish;
    153. }
    154. else
    155. insert_aux(position, x);
    156. return begin() + n;
    157. }
    158. iterator insert(iterator position) { return insert(position, T()); }
    159. #ifdef __STL_MEMBER_TEMPLATES
    160. template <class InputIterator>
    161. void insert(iterator position, InputIterator first, InputIterator last) {
    162. range_insert(position, first, last, iterator_category(first));
    163. }
    164. #else /* __STL_MEMBER_TEMPLATES */
    165. void insert(iterator position,
    166. const_iterator first, const_iterator last);
    167. #endif /* __STL_MEMBER_TEMPLATES */
    168. void insert (iterator pos, size_type n, const T& x);
    169. void insert (iterator pos, int n, const T& x) {
    170. insert(pos, (size_type) n, x);
    171. }
    172. void insert (iterator pos, long n, const T& x) {
    173. insert(pos, (size_type) n, x);
    174. }
    175. void pop_back() {
    176. --finish;
    177. destroy(finish);
    178. }
    179. iterator erase(iterator position) {
    180. if (position + 1 != end())
    181. copy(position + 1, finish, position);
    182. --finish;
    183. destroy(finish);
    184. return position;
    185. }
    186. iterator erase(iterator first, iterator last) {
    187. iterator i = copy(last, finish, first);
    188. destroy(i, finish);
    189. finish = finish - (last - first);
    190. return first;
    191. }
    192. void resize(size_type new_size, const T& x) {
    193. if (new_size < size())
    194. erase(begin() + new_size, end());
    195. else
    196. insert(end(), new_size - size(), x);
    197. }
    198. void resize(size_type new_size) { resize(new_size, T()); }
    199. void clear() { erase(begin(), end()); }
    200. protected:
    201. iterator allocate_and_fill(size_type n, const T& x) {
    202. iterator result = data_allocator::allocate(n);
    203. __STL_TRY {
    204. uninitialized_fill_n(result, n, x);
    205. return result;
    206. }
    207. __STL_UNWIND(data_allocator::deallocate(result, n));
    208. }
    209. #ifdef __STL_MEMBER_TEMPLATES
    210. template <class ForwardIterator>
    211. iterator allocate_and_copy(size_type n,
    212. ForwardIterator first, ForwardIterator last) {
    213. iterator result = data_allocator::allocate(n);
    214. __STL_TRY {
    215. uninitialized_copy(first, last, result);
    216. return result;
    217. }
    218. __STL_UNWIND(data_allocator::deallocate(result, n));
    219. }
    220. #else /* __STL_MEMBER_TEMPLATES */
    221. iterator allocate_and_copy(size_type n,
    222. const_iterator first, const_iterator last) {
    223. iterator result = data_allocator::allocate(n);
    224. __STL_TRY {
    225. uninitialized_copy(first, last, result);
    226. return result;
    227. }
    228. __STL_UNWIND(data_allocator::deallocate(result, n));
    229. }
    230. #endif /* __STL_MEMBER_TEMPLATES */
    231. #ifdef __STL_MEMBER_TEMPLATES
    232. template <class InputIterator>
    233. void range_initialize(InputIterator first, InputIterator last,
    234. input_iterator_tag) {
    235. for ( ; first != last; ++first)
    236. push_back(*first);
    237. }
    238. // This function is only called by the constructor. We have to worry
    239. // about resource leaks, but not about maintaining invariants.
    240. template <class ForwardIterator>
    241. void range_initialize(ForwardIterator first, ForwardIterator last,
    242. forward_iterator_tag) {
    243. size_type n = 0;
    244. distance(first, last, n);
    245. start = allocate_and_copy(n, first, last);
    246. finish = start + n;
    247. end_of_storage = finish;
    248. }
    249. template <class InputIterator>
    250. void range_insert(iterator pos,
    251. InputIterator first, InputIterator last,
    252. input_iterator_tag);
    253. template <class ForwardIterator>
    254. void range_insert(iterator pos,
    255. ForwardIterator first, ForwardIterator last,
    256. forward_iterator_tag);
    257. #endif /* __STL_MEMBER_TEMPLATES */
    258. };
    259. template <class T, class Alloc>
    260. inline bool operator==(const vector& x, const vector& y) {
    261. return x.size() == y.size() && equal(x.begin(), x.end(), y.begin());
    262. }
    263. template <class T, class Alloc>
    264. inline bool operator<(const vector& x, const vector& y) {
    265. return lexicographical_compare(x.begin(), x.end(), y.begin(), y.end());
    266. }
    267. #ifdef __STL_FUNCTION_TMPL_PARTIAL_ORDER
    268. template <class T, class Alloc>
    269. inline void swap(vector& x, vector& y) {
    270. x.swap(y);
    271. }
    272. #endif /* __STL_FUNCTION_TMPL_PARTIAL_ORDER */
    273. template <class T, class Alloc>
    274. vector& vector::operator=(const vector& x) {
    275. if (&x != this) {
    276. if (x.size() > capacity()) {
    277. iterator tmp = allocate_and_copy(x.end() - x.begin(),
    278. x.begin(), x.end());
    279. destroy(start, finish);
    280. deallocate();
    281. start = tmp;
    282. end_of_storage = start + (x.end() - x.begin());
    283. }
    284. else if (size() >= x.size()) {
    285. iterator i = copy(x.begin(), x.end(), begin());
    286. destroy(i, finish);
    287. }
    288. else {
    289. copy(x.begin(), x.begin() + size(), start);
    290. uninitialized_copy(x.begin() + size(), x.end(), finish);
    291. }
    292. finish = start + x.size();
    293. }
    294. return *this;
    295. }
    296. template <class T, class Alloc>
    297. void vector::insert_aux(iterator position, const T& x) {
    298. if (finish != end_of_storage) {
    299. construct(finish, *(finish - 1));
    300. ++finish;
    301. T x_copy = x;
    302. copy_backward(position, finish - 2, finish - 1);
    303. *position = x_copy;
    304. }
    305. else {
    306. const size_type old_size = size();
    307. const size_type len = old_size != 0 ? 2 * old_size : 1;
    308. iterator new_start = data_allocator::allocate(len);
    309. iterator new_finish = new_start;
    310. __STL_TRY {
    311. new_finish = uninitialized_copy(start, position, new_start);
    312. construct(new_finish, x);
    313. ++new_finish;
    314. new_finish = uninitialized_copy(position, finish, new_finish);
    315. }
    316. # ifdef __STL_USE_EXCEPTIONS
    317. catch(...) {
    318. destroy(new_start, new_finish);
    319. data_allocator::deallocate(new_start, len);
    320. throw;
    321. }
    322. # endif /* __STL_USE_EXCEPTIONS */
    323. destroy(begin(), end());
    324. deallocate();
    325. start = new_start;
    326. finish = new_finish;
    327. end_of_storage = new_start + len;
    328. }
    329. }
    330. template <class T, class Alloc>
    331. void vector::insert(iterator position, size_type n, const T& x) {
    332. if (n != 0) {
    333. if (size_type(end_of_storage - finish) >= n) {
    334. T x_copy = x;
    335. const size_type elems_after = finish - position;
    336. iterator old_finish = finish;
    337. if (elems_after > n) {
    338. uninitialized_copy(finish - n, finish, finish);
    339. finish += n;
    340. copy_backward(position, old_finish - n, old_finish);
    341. fill(position, position + n, x_copy);
    342. }
    343. else {
    344. uninitialized_fill_n(finish, n - elems_after, x_copy);
    345. finish += n - elems_after;
    346. uninitialized_copy(position, old_finish, finish);
    347. finish += elems_after;
    348. fill(position, old_finish, x_copy);
    349. }
    350. }
    351. else {
    352. const size_type old_size = size();
    353. const size_type len = old_size + max(old_size, n);
    354. iterator new_start = data_allocator::allocate(len);
    355. iterator new_finish = new_start;
    356. __STL_TRY {
    357. new_finish = uninitialized_copy(start, position, new_start);
    358. new_finish = uninitialized_fill_n(new_finish, n, x);
    359. new_finish = uninitialized_copy(position, finish, new_finish);
    360. }
    361. # ifdef __STL_USE_EXCEPTIONS
    362. catch(...) {
    363. destroy(new_start, new_finish);
    364. data_allocator::deallocate(new_start, len);
    365. throw;
    366. }
    367. # endif /* __STL_USE_EXCEPTIONS */
    368. destroy(start, finish);
    369. deallocate();
    370. start = new_start;
    371. finish = new_finish;
    372. end_of_storage = new_start + len;
    373. }
    374. }
    375. }
    376. #ifdef __STL_MEMBER_TEMPLATES
    377. template <class T, class Alloc> template <class InputIterator>
    378. void vector::range_insert(iterator pos,
    379. InputIterator first, InputIterator last,
    380. input_iterator_tag) {
    381. for ( ; first != last; ++first) {
    382. pos = insert(pos, *first);
    383. ++pos;
    384. }
    385. }
    386. template <class T, class Alloc> template <class ForwardIterator>
    387. void vector::range_insert(iterator position,
    388. ForwardIterator first,
    389. ForwardIterator last,
    390. forward_iterator_tag) {
    391. if (first != last) {
    392. size_type n = 0;
    393. distance(first, last, n);
    394. if (size_type(end_of_storage - finish) >= n) {
    395. const size_type elems_after = finish - position;
    396. iterator old_finish = finish;
    397. if (elems_after > n) {
    398. uninitialized_copy(finish - n, finish, finish);
    399. finish += n;
    400. copy_backward(position, old_finish - n, old_finish);
    401. copy(first, last, position);
    402. }
    403. else {
    404. ForwardIterator mid = first;
    405. advance(mid, elems_after);
    406. uninitialized_copy(mid, last, finish);
    407. finish += n - elems_after;
    408. uninitialized_copy(position, old_finish, finish);
    409. finish += elems_after;
    410. copy(first, mid, position);
    411. }
    412. }
    413. else {
    414. const size_type old_size = size();
    415. const size_type len = old_size + max(old_size, n);
    416. iterator new_start = data_allocator::allocate(len);
    417. iterator new_finish = new_start;
    418. __STL_TRY {
    419. new_finish = uninitialized_copy(start, position, new_start);
    420. new_finish = uninitialized_copy(first, last, new_finish);
    421. new_finish = uninitialized_copy(position, finish, new_finish);
    422. }
    423. # ifdef __STL_USE_EXCEPTIONS
    424. catch(...) {
    425. destroy(new_start, new_finish);
    426. data_allocator::deallocate(new_start, len);
    427. throw;
    428. }
    429. # endif /* __STL_USE_EXCEPTIONS */
    430. destroy(start, finish);
    431. deallocate();
    432. start = new_start;
    433. finish = new_finish;
    434. end_of_storage = new_start + len;
    435. }
    436. }
    437. }
    438. #else /* __STL_MEMBER_TEMPLATES */
    439. template <class T, class Alloc>
    440. void vector::insert(iterator position,
    441. const_iterator first,
    442. const_iterator last) {
    443. if (first != last) {
    444. size_type n = 0;
    445. distance(first, last, n);
    446. if (size_type(end_of_storage - finish) >= n) {
    447. const size_type elems_after = finish - position;
    448. iterator old_finish = finish;
    449. if (elems_after > n) {
    450. uninitialized_copy(finish - n, finish, finish);
    451. finish += n;
    452. copy_backward(position, old_finish - n, old_finish);
    453. copy(first, last, position);
    454. }
    455. else {
    456. uninitialized_copy(first + elems_after, last, finish);
    457. finish += n - elems_after;
    458. uninitialized_copy(position, old_finish, finish);
    459. finish += elems_after;
    460. copy(first, first + elems_after, position);
    461. }
    462. }
    463. else {
    464. const size_type old_size = size();
    465. const size_type len = old_size + max(old_size, n);
    466. iterator new_start = data_allocator::allocate(len);
    467. iterator new_finish = new_start;
    468. __STL_TRY {
    469. new_finish = uninitialized_copy(start, position, new_start);
    470. new_finish = uninitialized_copy(first, last, new_finish);
    471. new_finish = uninitialized_copy(position, finish, new_finish);
    472. }
    473. # ifdef __STL_USE_EXCEPTIONS
    474. catch(...) {
    475. destroy(new_start, new_finish);
    476. data_allocator::deallocate(new_start, len);
    477. throw;
    478. }
    479. # endif /* __STL_USE_EXCEPTIONS */
    480. destroy(start, finish);
    481. deallocate();
    482. start = new_start;
    483. finish = new_finish;
    484. end_of_storage = new_start + len;
    485. }
    486. }
    487. }
    488. #endif /* __STL_MEMBER_TEMPLATES */
    489. #if defined(__sgi) && !defined(__GNUC__) && (_MIPS_SIM != _MIPS_SIM_ABI32)
    490. #pragma reset woff 1174
    491. #endif
    492. __STL_END_NAMESPACE
    493. #endif /* __SGI_STL_INTERNAL_VECTOR_H */
    494. // Local Variables:
    495. // mode:C++
    496. // End:

  • 相关阅读:
    4.2冰达机器人:视觉实例-机器人视觉循线、视觉实例-调整循线颜色
    关于 Git 重写历史的一些笔记
    计算机毕业设计 基于SSM的在线预约导游系统的设计与实现 Java实战项目 附源码+文档+视频讲解
    Unity3d-异步加载场景、进度条加载
    基于SSM的智慧城市实验室主页系统的设计与实现
    spring中那些让你爱不释手的代码技巧(续集)
    tcp滑动窗口原理
    信钰证券:碧桂园大涨,石墨烯拉升
    GBase 8c结果集类型
    原子的核型结构及氢原子的波尔理论
  • 原文地址:https://blog.csdn.net/weixin_62684026/article/details/126335773