目录
这里我们先将每一个小模块分别实现,然后最终的汇总代码和测试代码在后面
- #pragma once
- #include
- #include
- namespace zhuyuan
- {
- template<class T>
- class vector
- {
- public:
-
- private:
- //_start是容器的初始位置
- iterator _start;
- //finish是最后一个数据的下一个位置
- iterator _finish;
- //_end_of_storage是我们整个vector的容量大小
- iterator _end_of_storage;
- };
- }
- //空参构造器
- vector()
- :_start(nullptr)
- ,_finish(nullptr)
- ,_end_of_storage(nullptr)
- {
-
- }
- //析构函数
- ~vector()
- {
- //析构的时候只要将整一个空间的首元素的地址传过去就可以了。
- delete[] _start;
- _start=_finish=_end_of_storage= nullptr;
- }
其实连续的空间的迭代器可以用指针来实现
- typedef T* iterator;
- const typedef T* const_iterator;
- iterator begin()
- {
- return _start;
- }
- const iterator begin() const
- {
- return _start;
- }
- iterator end()
- {
- return _finish;
- }
- const iterator end() const
- {
- return _finish;
- }
_end_of_storage表示的是容器中当前开辟的空间的最后位置的迭代器。
_start表示的是当前的容器的首元素的位置
_finish表示的当前容器中最后一个元素的下一个位置
capacity表示的是当前容器的容量大小
size表示的是当前容器中存储的元素个数
- size_t capacity() const
- {
- return _end_of_storage-_start;
- }
- size_t size() const
- {
- return _finish-_start;
- }
对我们两个容器中的每一个成员变量都进行交换,交换可以直接调用我们的std中的交换函数。
- void swap(vector
& v) - {
- std::swap(_start, v._start);
- std::swap(_finish, v._finish);
- std::swap(_end_of_storage, v._endOfStorage);
- }
- //将要拷贝的迭代器的范围传入
- vector(iterator first,iterator last)
- :_start(nullptr)
- ,_finish(nullptr)
- ,_end_of_storage(nullptr)
- {
- reserve(last-first+1);
- iterator it=begin();
- for(int i=0;i
- {
- *it=*(first+i);
- it++;
- }
- _finish=_start+(last-first);
- }
-
测试代码
- void myvector_test9()
- {
- vector<int> v1;
- v1.push_back(1);
- v1.push_back(2);
- vector<int> v2(v1.begin(),v1.end());
- cout<
1]< - }
2.拷贝构造
- vector(const vector
& v) - : _start(nullptr)
- , _finish(nullptr)
- , _end_of_storage(nullptr)
- {
- reserve(v.capacity());
- iterator it = begin();
- const_iterator vit = v.begin();
- while (vit != v.end())
- {
- *it++ = *vit++;
- }
- _finish = it;
- }
测试代码
- void myvector_test8()
- {
- vector<int> v1;
- v1.push_back(1);
- v1.push_back(2);
- vector<int> v2(v1);
- vector<int>::iterator it=v2.begin();
- while(it!=v2.end())
- {
- cout<<*it<<" ";
- it++;
- }
- cout<
- }
3.使用=拷贝构造
这里我们可以采用和之前字符串中一样的老板式的写法
由于编译器在将v传过来的时候会拷贝构造一个v,将这个v与我们当前的容器中的内容交换一下,我们的当前容器就完成拷贝了
- vector
&operator =(vector v) - {
- swap(v);
- return *this;
- }
- void myvector_test10()
- {
- vector<int> v1;
- v1.push_back(1);
- v1.push_back(2);
- vector<int> v2=v1;
- vector<int>::iterator it1=v1.begin();
- while(it1!=v1.end())
- {
- cout<<*it1<<" ";
- it1++;
- }
- cout<
- vector<int>::iterator it2=v2.begin();
- while(it2!=v2.end())
- {
- cout<<*it2<<" ";
- it2++;
- }
- cout<
- }
七、扩容操作
1.reserve扩容
reserve如果传入的数据比当前的空间大小小的话是不会处理的。
- //开辟n个空间
- void reserve(size_t n)
- {
- if(n>capacity())
- {
- size_t sz=size();
- T*tmp=new T[n];
- if(_start)
- {
- memcpy(tmp,_start,sizeof(T)*size());
- delete[] _start;
- }
- _start=tmp;
- _finish=_start+sz;
- //由于上面的过程中我们将原先的_start给销毁了,新的_start变成了tmp
- //所以其size可能会发生变化,
- // _finish=_start+size();
- _end_of_storage=_start+n;
- }
- }
2.resize调整大小
- //resize第一个参数是要调整到的大小,第二个参数是如果调整出来的大小大于了原来的数据用什么值填充
- void resize(size_t n,const T&value=T())
- {
- //1.如果n小于当前的size,则数据个数缩小到n
- if(n<=size())
- {
- _finish=_start+n;
- return;
- }
- //2.空间不够则增容
- if(n>capacity())
- {
- reserve(n);
- }
- //3.将size扩大到n
- iterator it=_finish;
- _finish=_start+n;
- while(it!=_finish)
- {
- *it=value;
- ++it;
- }
-
- }
测试代码
- void myvector_test11()
- {
- vector<int> v1;
- v1.push_back(1);
- v1.push_back(2);
- v1.push_back(3);
- v1.push_back(4);
- vector<int>::iterator it1=v1.begin();
- while(it1!=v1.end())
- {
- cout<<*it1<<" ";
- it1++;
- }
- cout<
- vector<int>v2=v1;
- v1.resize(7,5);
- vector<int>::iterator it2=v1.begin();
- while(it2!=v1.end())
- {
- cout<<*it2<<" ";
- it2++;
- }
- cout<
- }
八、让我们的容器支持随机读写
我们分别需要提供const类型的和非const类型的。
- const T&operator [](size_t pos) const
- {
- assert(pos<size());
- return _start[pos];
- }
-
- T&operator [](size_t pos)
- {
- assert(pos<size());
- return _start[pos];
- }
九、尾插尾删
1.尾插push_back
尾插要注意扩容
- //使用泛型,输入的是T类型
- void push_back(const T&x)
- {
- if(_finish==_end_of_storage)
- {
-
- reserve(capacity()==0?4 :capacity()*2);
-
- }
- //finish是最后一个数据的下一个位置
- *_finish=x;
- ++_finish;
- }
2.尾删 pop_back
尾删我们需要先判断一下当前的容器还有没有元素
- void pop_back()
- {
- assert(_finish>_start);
- --_finish;
- }
3.将容器后面追加n个元素,元素为value
- vector
v; - // 如果下面的这个push_back不加const,就会报错,因为拷贝的这个字符串具有隐式类型转换
- // 期间会生成一个中间的临时变量,而这个临时变量具有常性。如果不加const会发生权限的扩大。
- // v.push_back("xxxx")
- vector(size_t n, const T& value = T())
- : _start(nullptr)
- , _finish(nullptr)
- , _end_of_storage(nullptr)
- {
- reserve(n);
- while (n--)
- {
- push_back(value);
- }
- }
测试代码
- //使用迭代器遍历容器
- void Func(const vector<int>&v)
- {
- vector<int>::const_iterator it=v.begin();
- while(it!=v.end())
- {
- cout<<*it<<" ";
- ++it;
- }
- cout<
- }
- void myvector_test1()
- {
-
- vector<int> v;
- v.push_back(1);
- v.push_back(2);
- v.push_back(3);
- v.push_back(4);
- v.push_back(5);
- //使用随机读取的方式遍历
- for(size_t i=0;i
size();++i) - {
- cout<
" "; - }
- cout<
- vector<int>::iterator it=v.begin();
- while(it!=v.end())
- {
- cout<<*it<<" ";
- ++it;
- }
- cout<
-
- //使用范围for的形式遍历容器
- //有了迭代器就支持范围for,也就是调用我们的v.begin(),v.end()来执行相关的操作
- //const的话就走const的迭代器,
- for(auto e:v)
- {
- cout<
" "; - }
- v.pop_back();
- cout<
-
- Func(v);
- }
十、随机位置插入和删除
1.随机位置插入insert
迭代器失效就是当我们尾插数据的时候,如果发生了扩容,原来的地址空间可能就被转换到了一块更大的空间,所以我们迭代器的指针就失效了。所以我们如果发生了扩容就要及时更新指针。
- // void insert(iterator &pos ,const T& x)
- void insert(iterator pos ,const T& x)
- {
- assert(pos>=_start);
- //等于finish就是尾插
- assert(pos<=_finish);
- if(_finish==_end_of_storage)
- {
- //如果发生了扩容就要重新调整我们的pos指针的位置,不然就会发生迭代器失效的问题
- size_t len=pos-_start;
- reserve(capacity()==0? 4:capacity()*2);
- //形参是实参的拷贝,并不会真正去改变我们外部的pos
- //仅仅只能保证我们下面的pos使用是正常的
- pos=_start+len;
- }
- //挪动数据
- iterator end=_finish -1;
- while(end>=pos)
- {
- *(end+1)=*end;
- --end;
- }
- *pos=x;
- ++_finish;
- }
2.随机位置擦除
随机位置擦除的话可以使用缩容来优化我们过大的空间,但是这是一种时间换空间的做法,一般不用做。可以将下面代码中的缩容那部分注释掉。
- //stl规定erase返回删除位置的下一个位置迭代器
- iterator erase(iterator pos)
- {
- assert(pos>=_start);
- assert(pos<_finish);
-
- iterator begin=pos+1;
- //将当前位置不断挪动到前一个位置
- while(begin<_finish)
- {
- *(begin-1)=*begin;
- ++begin;
- }
- --_finish;
-
- if(size()<capacity()/2)
- {
- //缩容,以时间换空间。
- _end_of_storage=_start+capacity()/2;
- }
- return pos;
- }
3.清除函数clear
1)写法一:调用erase
- void clear()
- {
- while(_finish!=_start)
- {
- erase(_start);
- }
- }
2)写法二:直接将_finish=_start
- void clear()
- {
- _finish = _start;
- }
测试代码
- void myvector_test3()
- {
- vector<int> v;
- v.push_back(1);
- v.push_back(2);
- v.push_back(3);
- v.push_back(4);
- // v.push_back(5);
-
- for(size_t i=0;i
size();++i) - {
- cout<
" "; - }
- cout<
-
- v.erase(v.begin());
- for(size_t i=0;i
size();++i) - {
- cout<
" "; - }
- cout<
- }
测试代码(clear)
- void myvector_test13()
- {
- vector<int> v1;
- v1.push_back(1);
- v1.push_back(2);
- v1.push_back(3);
- vector<int>::iterator it=v1.begin();
- while(it!=v1.end())
- {
- cout<<*it<<" ";
- it++;
- }
- cout<
- v1.clear();
- vector<int>::iterator it2=v1.begin();
- while(it2!=v1.end())
- {
- cout<<*it2<<" ";
- it2++;
- }
- cout<
- }
为什么要返回删除位置的下一个位置的迭代器?
观察下面几个代码的变化和问题
- void myvector_test4()
- {
- //正常运行
- vector<int> v;
- v.push_back(1);
- v.push_back(2);
- v.push_back(3);
- v.push_back(4);
- v.push_back(5);
-
- //要求删除所有的偶数
- auto it=v.begin();
- while(it!=v.end())
- {
- if(*it%2==0)
- {
- v.erase(it);
- }
- ++it;
- }
-
- for(size_t i=0;i
size();++i) - {
- cout<
" "; - }
- cout<
- }
相比于上面 这里我们少push_back了5
- //崩溃
- void myvector_test5()
- {
- vector<int> v;
- v.push_back(1);
- v.push_back(2);
- v.push_back(3);
- v.push_back(4);
-
- //要求删除所有的偶数
- auto it=v.begin();
- while(it!=v.end())
- {
- if(*it%2==0)
- {
- v.erase(it);
- }
- ++it;
- }
- for(size_t i=0;i
size();++i) - {
- cout<
" "; - }
- cout<
- }
- //4删不掉
- void myvector_test6()
- {
- //正常运行
- vector<int> v;
- v.push_back(1);
- v.push_back(2);
- v.push_back(4);
- v.push_back(3);
- v.push_back(4);
- v.push_back(5);
- v.push_back(5);
-
- //要求删除所有的偶数
- auto it=v.begin();
- while(it!=v.end())
- {
- if(*it%2==0)
- {
- v.erase(it);
- }
- ++it;
- }
-
- for(size_t i=0;i
size();++i) - {
- cout<
" "; - }
- cout<
- }
这里的4我们没删掉
正确的使用方式是我们在erase的时候就要同步更新我们的pos
- void myvector_test7()
- {
- //正常运行
- vector<int> v;
- v.push_back(1);
- v.push_back(2);
- v.push_back(4);
- v.push_back(3);
- v.push_back(4);
- v.push_back(5);
-
- //要求删除所有的偶数
- auto it=v.begin();
- while(it!=v.end())
- {
- if(*it%2==0)
- {
- //同步更新我们的it
- //如果删除了某个数据,it迭代器就不要继续往后走了
- //因为后面的数据会移动上来,it迭代器当前指向位置并没有检查过
- it=v.erase(it);
- }
- else
- {
- ++it;
- }
-
- }
- for(size_t i=0;i
size();++i) - {
- cout<
" "; - }
- cout<
- }
- //结论:insert/erase pos位置,不要直接访问pos。
- // 一定要更新,直接访问,可能会出现各种出乎意料的结果
- //这就是pos所谓的迭代器失效。
- //认为pos失效,不要访问。
- //结果不同的底层实现可能不一样。
十一、迭代器的失效问题
迭代器失效就是当我们尾插数据的时候,如果发生了扩容,原来的地址空间可能就被转换到了一块更大的空间,所以我们迭代器的指针就失效了。
- //迭代器失效问题
- void myvector_test2()
- {
- vector<int> v;
- v.push_back(1);
- v.push_back(2);
- v.push_back(3);
- v.push_back(4);
- // v.push_back(5);
-
- for(size_t i=0;i
size();++i) - {
- cout<
" "; - }
- cout<
-
- //这里由于我们之前扩容的写法(在上面的push_back中看),是初始开辟四个,然后超出的话空间直接乘以两倍,所以我们在第五个数据插入的时候就会发生扩容
- //在vector发生扩容的时候,我们的迭代器的指针就失效了,就会发生迭代器失效的问题
- auto p=find(v.begin(),v.end(),3);
- if(p!=v.end())
- {
- //在p位置插入数据以后,不要访问p,因为p可能失效
- v.insert(p,30);
- cout<<*p<
- //因为上面的insert30的时候p的指针已经失效了,所以会报错
- v.insert(p,40);
- }
-
- vector<int>::iterator it=v.begin();
- while(it!=v.end())
- {
- cout<<*it<<" ";
- ++it;
- }
- //如果上面的insert加了引用,下面这个代码就会报错。
- //传值返回的都是数据的临时拷贝,这个拷贝具有常性,不能被修改,会报错
- v.insert(v.begin(),1);
- }
问题的解决
我们同样可以仿照erase中的写法,将我们insert函数中当前的扩容之后的对应位置的迭代器返回,然后及时同步迭代器,从而解决这个问题。
- iterator insert(iterator pos ,const T& x)
- {
- assert(pos>=_start);
- //等于finish就是尾插
- assert(pos<=_finish);
- if(_finish==_end_of_storage)
- {
- //如果发生了扩容就要重新调整我们的pos指针的位置,不然就会发生迭代器失效的问题
- size_t len=pos-_start;
- reserve(capacity()==0? 4:capacity()*2);
- //形参是实参的拷贝,并不会真正去改变pos
- pos=_start+len;
- }
- //挪动数据
- iterator end=_finish -1;
- while(end>=pos)
- {
- *(end+1)=*end;
- --end;
- }
- *pos=x;
- ++_finish;
- return pos;
- }
测试代码
- //迭代器失效问题
- void myvector_test12()
- {
- vector<int> v;
- v.push_back(1);
- v.push_back(2);
- v.push_back(3);
- v.push_back(4);
- // v.push_back(5);
-
- for(size_t i=0;i
size();++i) - {
- cout<
" "; - }
- cout<
-
- //在vector发生扩容的时候,我们的迭代器的指针就失效了,就会发生迭代器失效的问题
- auto p=find(v.begin(),v.end(),3);
- if(p!=v.end())
- {
- //在p位置插入数据以后,及时同步指针
- p=v.insert(p,30);
- for(size_t i=0;i
size();++i) - {
- cout<
" "; - }
- cout<
- p=v.insert(p,40);
- }
-
- vector<int>::iterator it=v.begin();
- while(it!=v.end())
- {
- cout<<*it<<" ";
- ++it;
- }
- }
十二、主程序代码汇总
-
- #ifndef VECTORTEST_MYVECTOR_H
- #define VECTORTEST_MYVECTOR_H
- #pragma once
- #include
- #include
- namespace zhuyuan
- {
- template<class T>
- class vector
- {
- public:
- typedef T* iterator;
- const typedef T* const_iterator;
- iterator begin()
- {
- return _start;
- }
- const iterator begin() const
- {
- return _start;
- }
- iterator end()
- {
- return _finish;
- }
- const iterator end() const
- {
- return _finish;
- }
- vector()
- :_start(nullptr)
- ,_finish(nullptr)
- ,_end_of_storage(nullptr)
- {
-
- }
-
- ~vector()
- {
- delete[] _start;
- _start=_finish=_end_of_storage= nullptr;
- }
-
- size_t capacity() const
- {
- return _end_of_storage-_start;
- }
- size_t size() const
- {
- return _finish-_start;
- }
- // vector
v; - // 如果下面的这个push_back不加const,就会报错,因为拷贝的这个字符串具有隐式类型转换
- // 期间会生成一个中间的临时变量,而这个临时变量具有常性。如果不加const会发生权限的扩大。
- // v.push_back("xxxx")
- vector(size_t n, const T& value = T())
- : _start(nullptr)
- , _finish(nullptr)
- , _end_of_storage(nullptr)
- {
- reserve(n);
- while (n--)
- {
- push_back(value);
- }
- }
- vector(iterator first,iterator last)
- :_start(nullptr)
- ,_finish(nullptr)
- ,_end_of_storage(nullptr)
- {
- reserve(last-first+1);
- iterator it=begin();
- for(int i=0;i
- {
- *it=*(first+i);
- it++;
- }
- _finish=_start+(last-first);
- }
-
- vector(const vector
& v) - : _start(nullptr)
- , _finish(nullptr)
- , _end_of_storage(nullptr)
- {
- reserve(v.capacity());
- iterator it = begin();
- const_iterator vit = v.begin();
- while (vit != v.end())
- {
- *it++ = *vit++;
- }
- _finish = it;
- }
- vector
&operator =(vector v) - {
- swap(v);
- return *this;
- }
- void swap(vector
& v) - {
- std::swap(_start, v._start);
- std::swap(_finish, v._finish);
- std::swap(_end_of_storage, v._endOfStorage);
- }
- //开辟n个空间
- void reserve(size_t n)
- {
- if(n>capacity())
- {
- size_t sz=size();
- T*tmp=new T[n];
- if(_start)
- {
- memcpy(tmp,_start,sizeof(T)*size());
- delete[] _start;
- }
- _start=tmp;
- _finish=_start+sz;
- //由于上面的过程中我们将原先的_start给销毁了,新的_start变成了tmp
- //所以其size可能会发生变化,
- // _finish=_start+size();
- _end_of_storage=_start+n;
- }
- }
- //resize第一个参数是要调整到的大小,第二个参数是如果调整出来的大小大于了原来的数据用什么值填充
- void resize(size_t n,const T&value=T())
- {
- //1.如果n小于当前的size,则数据个数缩小到n
- if(n<=size())
- {
- _finish=_start+n;
- return;
- }
- //2.空间不够则增容
- if(n>capacity())
- {
- reserve(n);
- }
- //3.将size扩大到n
- iterator it=_finish;
- _finish=_start+n;
- while(it!=_finish)
- {
- *it=value;
- ++it;
- }
-
- }
-
- const T&operator [](size_t pos) const
- {
- assert(pos<size());
- return _start[pos];
- }
-
- T&operator [](size_t pos)
- {
- assert(pos<size());
- return _start[pos];
- }
- //使用泛型,输入的是T类型
- void push_back(const T&x)
- {
- if(_finish==_end_of_storage)
- {
-
- reserve(capacity()==0?4 :capacity()*2);
-
- }
- //finish是最后一个数据的下一个位置
- *_finish=x;
- ++_finish;
- }
-
- void pop_back()
- {
- assert(_finish>_start);
- --_finish;
- }
-
- // void insert(iterator &pos ,const T& x)
- iterator insert(iterator pos ,const T& x)
- {
- assert(pos>=_start);
- //等于finish就是尾插
- assert(pos<=_finish);
- if(_finish==_end_of_storage)
- {
- //如果发生了扩容就要重新调整我们的pos指针的位置,不然就会发生迭代器失效的问题
- size_t len=pos-_start;
- reserve(capacity()==0? 4:capacity()*2);
- //形参是实参的拷贝,并不会真正去改变pos
- pos=_start+len;
- }
- //挪动数据
- iterator end=_finish -1;
- while(end>=pos)
- {
- *(end+1)=*end;
- --end;
- }
- *pos=x;
- ++_finish;
- return pos;
- }
- //stl规定erase返回删除位置的下一个位置迭代器
- iterator erase(iterator pos)
- {
- assert(pos>=_start);
- assert(pos<_finish);
-
- iterator begin=pos+1;
- //将当前位置不断挪动到前一个位置
- while(begin<_finish)
- {
- *(begin-1)=*begin;
- ++begin;
- }
- --_finish;
-
- if(size()<capacity()/2)
- {
- //缩容,以时间换空间。
- _end_of_storage=_start+capacity()/2;
- }
- return pos;
- }
- private:
- iterator _start;
- //finish是最后一个数据的下一个位置
- iterator _finish;
- //_end_of_storage是我们整个vector的容量大小
- iterator _end_of_storage;
- };
-
-
- }
- #endif //VECTORTEST_MYVECTOR_H
十三、测试程序代码汇总
调用测试程序
- using namespace std;
- #include "myvector.h"
-
- int main()
- {
- try
- {
- zhuyuan::myvector_test1();
- }
- catch(std::exception&e)
- {
- std::cout<
what()< - }
- }
测试程序
- void Func(const vector<int>&v)
- {
- vector<int>::const_iterator it=v.begin();
- while(it!=v.end())
- {
- cout<<*it<<" ";
- ++it;
- }
- cout<
- }
- void myvector_test1()
- {
-
- vector<int> v;
- v.push_back(1);
- v.push_back(2);
- v.push_back(3);
- v.push_back(4);
- v.push_back(5);
-
- for(size_t i=0;i
size();++i) - {
- cout<
" "; - }
- cout<
- vector<int>::iterator it=v.begin();
- while(it!=v.end())
- {
- cout<<*it<<" ";
- ++it;
- }
- cout<
-
- //有了迭代器就支持范围for,也就是调用我们的v.begin(),v.end()来执行相关的操作
- //const的话就走const的迭代器,
- for(auto e:v)
- {
- cout<
" "; - }
- v.pop_back();
- cout<
-
- Func(v);
- }
- //迭代器失效问题
- void myvector_test2()
- {
- vector<int> v;
- v.push_back(1);
- v.push_back(2);
- v.push_back(3);
- v.push_back(4);
- // v.push_back(5);
-
- for(size_t i=0;i
size();++i) - {
- cout<
" "; - }
- cout<
-
- //在vector发生扩容的时候,我们的迭代器的指针就失效了,就会发生迭代器失效的问题
- auto p=find(v.begin(),v.end(),3);
- if(p!=v.end())
- {
- //在p位置插入数据以后,不要访问p,因为p可能失效
- v.insert(p,30);
- cout<<*p<
- v.insert(p,40);
- }
-
- vector<int>::iterator it=v.begin();
- while(it!=v.end())
- {
- cout<<*it<<" ";
- ++it;
- }
- //如果上面的insert加了引用,下面这个代码就会报错。
- //传值返回的都是数据的临时拷贝,这个拷贝具有常性,不能被修改,会报错
- v.insert(v.begin(),1);
- }
- void myvector_test3()
- {
- vector<int> v;
- v.push_back(1);
- v.push_back(2);
- v.push_back(3);
- v.push_back(4);
- // v.push_back(5);
-
- for(size_t i=0;i
size();++i) - {
- cout<
" "; - }
- cout<
-
- v.erase(v.begin());
- for(size_t i=0;i
size();++i) - {
- cout<
" "; - }
- cout<
- }
- void myvector_test4()
- {
- //正常运行
- vector<int> v;
- v.push_back(1);
- v.push_back(2);
- v.push_back(3);
- v.push_back(4);
- v.push_back(5);
-
- //要求删除所有的偶数
- auto it=v.begin();
- while(it!=v.end())
- {
- if(*it%2==0)
- {
- v.erase(it);
- }
- ++it;
- }
-
- for(size_t i=0;i
size();++i) - {
- cout<
" "; - }
- cout<
- }
-
- //崩溃
- void myvector_test5()
- {
- vector<int> v;
- v.push_back(1);
- v.push_back(2);
- v.push_back(3);
- v.push_back(4);
-
- //要求删除所有的偶数
- auto it=v.begin();
- while(it!=v.end())
- {
- cout<<"it"<<*it<
- // cout<<*it<
- if(*it%2==0)
- {
- cout<<"end()"<
end()-v.begin()< - v.erase(it);
- }
- ++it;
- }
- for(size_t i=0;i
size();++i) - {
- cout<
" "; - }
- cout<
- }
- //4删不掉
- void myvector_test6()
- {
- //正常运行
- vector<int> v;
- v.push_back(1);
- v.push_back(2);
- v.push_back(4);
- v.push_back(3);
- v.push_back(4);
- v.push_back(5);
- v.push_back(5);
-
- //要求删除所有的偶数
- auto it=v.begin();
- while(it!=v.end())
- {
- if(*it%2==0)
- {
- v.erase(it);
- }
- ++it;
- }
-
- for(size_t i=0;i
size();++i) - {
- cout<
" "; - }
- cout<
- }
- void myvector_test7()
- {
- //正常运行
- vector<int> v;
- v.push_back(1);
- v.push_back(2);
- v.push_back(4);
- v.push_back(3);
- v.push_back(4);
- v.push_back(5);
-
- //要求删除所有的偶数
- auto it=v.begin();
- while(it!=v.end())
- {
- if(*it%2==0)
- {
- it=v.erase(it);
- }
- else
- {
- ++it;
- }
-
- }
- for(size_t i=0;i
size();++i) - {
- cout<
" "; - }
- cout<
- }
- //结论:insert/erase pos位置,不要直接访问pos。
- // 一定要更新,直接访问,可能会出现各种出乎意料的结果
- //这就是pos所谓的迭代器失效。
- //认为pos失效,不要访问。
- //结果不同的底层实现可能不一样。
- void myvector_test8()
- {
- vector<int> v1;
- v1.push_back(1);
- v1.push_back(2);
- vector<int> v2(v1);
- vector<int>::iterator it=v2.begin();
- while(it!=v2.end())
- {
- cout<<*it<<" ";
- it++;
- }
- cout<
- }
-
- void myvector_test9()
- {
- vector<int> v1;
- v1.push_back(1);
- v1.push_back(2);
- vector<int> v2(v1.begin(),v1.end());
- cout<
1]< - }
- void myvector_test10()
- {
- vector<int> v1;
- v1.push_back(1);
- v1.push_back(2);
- vector<int> v2=v1;
- vector<int>::iterator it1=v1.begin();
- while(it1!=v1.end())
- {
- cout<<*it1<<" ";
- it1++;
- }
- cout<
- vector<int>::iterator it2=v2.begin();
- while(it2!=v2.end())
- {
- cout<<*it2<<" ";
- it2++;
- }
- cout<
- }
- void myvector_test11()
- {
- vector<int> v1;
- v1.push_back(1);
- v1.push_back(2);
- v1.push_back(3);
- v1.push_back(4);
- vector<int>::iterator it1=v1.begin();
- while(it1!=v1.end())
- {
- cout<<*it1<<" ";
- it1++;
- }
- cout<
- vector<int>v2=v1;
- v1.resize(7,5);
- vector<int>::iterator it2=v1.begin();
- while(it2!=v1.end())
- {
- cout<<*it2<<" ";
- it2++;
- }
- cout<
- }
-
-
- //迭代器失效问题
- void myvector_test12()
- {
- vector<int> v;
- v.push_back(1);
- v.push_back(2);
- v.push_back(3);
- v.push_back(4);
- // v.push_back(5);
-
- for(size_t i=0;i
size();++i) - {
- cout<
" "; - }
- cout<
-
- //在vector发生扩容的时候,我们的迭代器的指针就失效了,就会发生迭代器失效的问题
- auto p=find(v.begin(),v.end(),3);
- if(p!=v.end())
- {
- //在p位置插入数据以后,及时同步指针
- p=v.insert(p,30);
- for(size_t i=0;i
size();++i) - {
- cout<
" "; - }
- cout<
- p=v.insert(p,40);
- }
-
- vector<int>::iterator it=v.begin();
- while(it!=v.end())
- {
- cout<<*it<<" ";
- ++it;
- }
- }
十四、vector原码
可以对照原码查看我们上面的模拟实现代码
- /*
- *
- * Copyright (c) 1994
- * Hewlett-Packard Company
- *
- * Permission to use, copy, modify, distribute and sell this software
- * and its documentation for any purpose is hereby granted without fee,
- * provided that the above copyright notice appear in all copies and
- * that both that copyright notice and this permission notice appear
- * in supporting documentation. Hewlett-Packard Company makes no
- * representations about the suitability of this software for any
- * purpose. It is provided "as is" without express or implied warranty.
- *
- *
- * Copyright (c) 1996
- * Silicon Graphics Computer Systems, Inc.
- *
- * Permission to use, copy, modify, distribute and sell this software
- * and its documentation for any purpose is hereby granted without fee,
- * provided that the above copyright notice appear in all copies and
- * that both that copyright notice and this permission notice appear
- * in supporting documentation. Silicon Graphics makes no
- * representations about the suitability of this software for any
- * purpose. It is provided "as is" without express or implied warranty.
- */
-
- /* NOTE: This is an internal header file, included by other STL headers.
- * You should not attempt to use it directly.
- */
-
- #ifndef __SGI_STL_INTERNAL_VECTOR_H
- #define __SGI_STL_INTERNAL_VECTOR_H
-
- __STL_BEGIN_NAMESPACE
-
- #if defined(__sgi) && !defined(__GNUC__) && (_MIPS_SIM != _MIPS_SIM_ABI32)
- #pragma set woff 1174
- #endif
-
- template <class T, class Alloc = alloc>
- class vector {
- public:
- typedef T value_type;
- typedef value_type* pointer;
- typedef const value_type* const_pointer;
- typedef value_type* iterator;
- typedef const value_type* const_iterator;
- typedef value_type& reference;
- typedef const value_type& const_reference;
- typedef size_t size_type;
- typedef ptrdiff_t difference_type;
-
- #ifdef __STL_CLASS_PARTIAL_SPECIALIZATION
- typedef reverse_iterator
const_reverse_iterator; - typedef reverse_iterator
reverse_iterator; - #else /* __STL_CLASS_PARTIAL_SPECIALIZATION */
- typedef reverse_iterator
- difference_type> const_reverse_iterator;
- typedef reverse_iterator
- reverse_iterator;
- #endif /* __STL_CLASS_PARTIAL_SPECIALIZATION */
- protected:
- typedef simple_alloc
data_allocator; - iterator start;
- iterator finish;
- iterator end_of_storage;
- void insert_aux(iterator position, const T& x);
- void deallocate() {
- if (start) data_allocator::deallocate(start, end_of_storage - start);
- }
-
- void fill_initialize(size_type n, const T& value) {
- start = allocate_and_fill(n, value);
- finish = start + n;
- end_of_storage = finish;
- }
- public:
- iterator begin() { return start; }
- const_iterator begin() const { return start; }
- iterator end() { return finish; }
- const_iterator end() const { return finish; }
- reverse_iterator rbegin() { return reverse_iterator(end()); }
- const_reverse_iterator rbegin() const {
- return const_reverse_iterator(end());
- }
- reverse_iterator rend() { return reverse_iterator(begin()); }
- const_reverse_iterator rend() const {
- return const_reverse_iterator(begin());
- }
- size_type size() const { return size_type(end() - begin()); }
- size_type max_size() const { return size_type(-1) / sizeof(T); }
- size_type capacity() const { return size_type(end_of_storage - begin()); }
- bool empty() const { return begin() == end(); }
- reference operator[](size_type n) { return *(begin() + n); }
- const_reference operator[](size_type n) const { return *(begin() + n); }
-
- vector() : start(0), finish(0), end_of_storage(0) {}
- vector(size_type n, const T& value) { fill_initialize(n, value); }
- vector(int n, const T& value) { fill_initialize(n, value); }
- vector(long n, const T& value) { fill_initialize(n, value); }
- explicit vector(size_type n) { fill_initialize(n, T()); }
-
- vector(const vector
& x) { - start = allocate_and_copy(x.end() - x.begin(), x.begin(), x.end());
- finish = start + (x.end() - x.begin());
- end_of_storage = finish;
- }
- #ifdef __STL_MEMBER_TEMPLATES
- template <class InputIterator>
- vector(InputIterator first, InputIterator last) :
- start(0), finish(0), end_of_storage(0)
- {
- range_initialize(first, last, iterator_category(first));
- }
- #else /* __STL_MEMBER_TEMPLATES */
- vector(const_iterator first, const_iterator last) {
- size_type n = 0;
- distance(first, last, n);
- start = allocate_and_copy(n, first, last);
- finish = start + n;
- end_of_storage = finish;
- }
- #endif /* __STL_MEMBER_TEMPLATES */
- ~vector() {
- destroy(start, finish);
- deallocate();
- }
- vector
& operator=(const vector& x); - void reserve(size_type n) {
- if (capacity() < n) {
- const size_type old_size = size();
- iterator tmp = allocate_and_copy(n, start, finish);
- destroy(start, finish);
- deallocate();
- start = tmp;
- finish = tmp + old_size;
- end_of_storage = start + n;
- }
- }
- reference front() { return *begin(); }
- const_reference front() const { return *begin(); }
- reference back() { return *(end() - 1); }
- const_reference back() const { return *(end() - 1); }
- void push_back(const T& x) {
- if (finish != end_of_storage) {
- construct(finish, x);
- ++finish;
- }
- else
- insert_aux(end(), x);
- }
- void swap(vector
& x) { - __STD::swap(start, x.start);
- __STD::swap(finish, x.finish);
- __STD::swap(end_of_storage, x.end_of_storage);
- }
- iterator insert(iterator position, const T& x) {
- size_type n = position - begin();
- if (finish != end_of_storage && position == end()) {
- construct(finish, x);
- ++finish;
- }
- else
- insert_aux(position, x);
- return begin() + n;
- }
- iterator insert(iterator position) { return insert(position, T()); }
- #ifdef __STL_MEMBER_TEMPLATES
- template <class InputIterator>
- void insert(iterator position, InputIterator first, InputIterator last) {
- range_insert(position, first, last, iterator_category(first));
- }
- #else /* __STL_MEMBER_TEMPLATES */
- void insert(iterator position,
- const_iterator first, const_iterator last);
- #endif /* __STL_MEMBER_TEMPLATES */
-
- void insert (iterator pos, size_type n, const T& x);
- void insert (iterator pos, int n, const T& x) {
- insert(pos, (size_type) n, x);
- }
- void insert (iterator pos, long n, const T& x) {
- insert(pos, (size_type) n, x);
- }
-
- void pop_back() {
- --finish;
- destroy(finish);
- }
- iterator erase(iterator position) {
- if (position + 1 != end())
- copy(position + 1, finish, position);
- --finish;
- destroy(finish);
- return position;
- }
- iterator erase(iterator first, iterator last) {
- iterator i = copy(last, finish, first);
- destroy(i, finish);
- finish = finish - (last - first);
- return first;
- }
- void resize(size_type new_size, const T& x) {
- if (new_size < size())
- erase(begin() + new_size, end());
- else
- insert(end(), new_size - size(), x);
- }
- void resize(size_type new_size) { resize(new_size, T()); }
- void clear() { erase(begin(), end()); }
-
- protected:
- iterator allocate_and_fill(size_type n, const T& x) {
- iterator result = data_allocator::allocate(n);
- __STL_TRY {
- uninitialized_fill_n(result, n, x);
- return result;
- }
- __STL_UNWIND(data_allocator::deallocate(result, n));
- }
-
- #ifdef __STL_MEMBER_TEMPLATES
- template <class ForwardIterator>
- iterator allocate_and_copy(size_type n,
- ForwardIterator first, ForwardIterator last) {
- iterator result = data_allocator::allocate(n);
- __STL_TRY {
- uninitialized_copy(first, last, result);
- return result;
- }
- __STL_UNWIND(data_allocator::deallocate(result, n));
- }
- #else /* __STL_MEMBER_TEMPLATES */
- iterator allocate_and_copy(size_type n,
- const_iterator first, const_iterator last) {
- iterator result = data_allocator::allocate(n);
- __STL_TRY {
- uninitialized_copy(first, last, result);
- return result;
- }
- __STL_UNWIND(data_allocator::deallocate(result, n));
- }
- #endif /* __STL_MEMBER_TEMPLATES */
-
-
- #ifdef __STL_MEMBER_TEMPLATES
- template <class InputIterator>
- void range_initialize(InputIterator first, InputIterator last,
- input_iterator_tag) {
- for ( ; first != last; ++first)
- push_back(*first);
- }
-
- // This function is only called by the constructor. We have to worry
- // about resource leaks, but not about maintaining invariants.
- template <class ForwardIterator>
- void range_initialize(ForwardIterator first, ForwardIterator last,
- forward_iterator_tag) {
- size_type n = 0;
- distance(first, last, n);
- start = allocate_and_copy(n, first, last);
- finish = start + n;
- end_of_storage = finish;
- }
-
- template <class InputIterator>
- void range_insert(iterator pos,
- InputIterator first, InputIterator last,
- input_iterator_tag);
-
- template <class ForwardIterator>
- void range_insert(iterator pos,
- ForwardIterator first, ForwardIterator last,
- forward_iterator_tag);
-
- #endif /* __STL_MEMBER_TEMPLATES */
- };
-
- template <class T, class Alloc>
- inline bool operator==(const vector
& x, const vector& y) { - return x.size() == y.size() && equal(x.begin(), x.end(), y.begin());
- }
-
- template <class T, class Alloc>
- inline bool operator<(const vector
& x, const vector& y) { - return lexicographical_compare(x.begin(), x.end(), y.begin(), y.end());
- }
-
- #ifdef __STL_FUNCTION_TMPL_PARTIAL_ORDER
-
- template <class T, class Alloc>
- inline void swap(vector
& x, vector& y) { - x.swap(y);
- }
-
- #endif /* __STL_FUNCTION_TMPL_PARTIAL_ORDER */
-
- template <class T, class Alloc>
- vector
& vector::operator=(const vector& x) { - if (&x != this) {
- if (x.size() > capacity()) {
- iterator tmp = allocate_and_copy(x.end() - x.begin(),
- x.begin(), x.end());
- destroy(start, finish);
- deallocate();
- start = tmp;
- end_of_storage = start + (x.end() - x.begin());
- }
- else if (size() >= x.size()) {
- iterator i = copy(x.begin(), x.end(), begin());
- destroy(i, finish);
- }
- else {
- copy(x.begin(), x.begin() + size(), start);
- uninitialized_copy(x.begin() + size(), x.end(), finish);
- }
- finish = start + x.size();
- }
- return *this;
- }
-
- template <class T, class Alloc>
- void vector
::insert_aux(iterator position, const T& x) { - if (finish != end_of_storage) {
- construct(finish, *(finish - 1));
- ++finish;
- T x_copy = x;
- copy_backward(position, finish - 2, finish - 1);
- *position = x_copy;
- }
- else {
- const size_type old_size = size();
- const size_type len = old_size != 0 ? 2 * old_size : 1;
- iterator new_start = data_allocator::allocate(len);
- iterator new_finish = new_start;
- __STL_TRY {
- new_finish = uninitialized_copy(start, position, new_start);
- construct(new_finish, x);
- ++new_finish;
- new_finish = uninitialized_copy(position, finish, new_finish);
- }
-
- # ifdef __STL_USE_EXCEPTIONS
- catch(...) {
- destroy(new_start, new_finish);
- data_allocator::deallocate(new_start, len);
- throw;
- }
- # endif /* __STL_USE_EXCEPTIONS */
- destroy(begin(), end());
- deallocate();
- start = new_start;
- finish = new_finish;
- end_of_storage = new_start + len;
- }
- }
-
- template <class T, class Alloc>
- void vector
::insert(iterator position, size_type n, const T& x) { - if (n != 0) {
- if (size_type(end_of_storage - finish) >= n) {
- T x_copy = x;
- const size_type elems_after = finish - position;
- iterator old_finish = finish;
- if (elems_after > n) {
- uninitialized_copy(finish - n, finish, finish);
- finish += n;
- copy_backward(position, old_finish - n, old_finish);
- fill(position, position + n, x_copy);
- }
- else {
- uninitialized_fill_n(finish, n - elems_after, x_copy);
- finish += n - elems_after;
- uninitialized_copy(position, old_finish, finish);
- finish += elems_after;
- fill(position, old_finish, x_copy);
- }
- }
- else {
- const size_type old_size = size();
- const size_type len = old_size + max(old_size, n);
- iterator new_start = data_allocator::allocate(len);
- iterator new_finish = new_start;
- __STL_TRY {
- new_finish = uninitialized_copy(start, position, new_start);
- new_finish = uninitialized_fill_n(new_finish, n, x);
- new_finish = uninitialized_copy(position, finish, new_finish);
- }
- # ifdef __STL_USE_EXCEPTIONS
- catch(...) {
- destroy(new_start, new_finish);
- data_allocator::deallocate(new_start, len);
- throw;
- }
- # endif /* __STL_USE_EXCEPTIONS */
- destroy(start, finish);
- deallocate();
- start = new_start;
- finish = new_finish;
- end_of_storage = new_start + len;
- }
- }
- }
-
- #ifdef __STL_MEMBER_TEMPLATES
-
- template <class T, class Alloc> template <class InputIterator>
- void vector
::range_insert(iterator pos, - InputIterator first, InputIterator last,
- input_iterator_tag) {
- for ( ; first != last; ++first) {
- pos = insert(pos, *first);
- ++pos;
- }
- }
-
- template <class T, class Alloc> template <class ForwardIterator>
- void vector
::range_insert(iterator position, - ForwardIterator first,
- ForwardIterator last,
- forward_iterator_tag) {
- if (first != last) {
- size_type n = 0;
- distance(first, last, n);
- if (size_type(end_of_storage - finish) >= n) {
- const size_type elems_after = finish - position;
- iterator old_finish = finish;
- if (elems_after > n) {
- uninitialized_copy(finish - n, finish, finish);
- finish += n;
- copy_backward(position, old_finish - n, old_finish);
- copy(first, last, position);
- }
- else {
- ForwardIterator mid = first;
- advance(mid, elems_after);
- uninitialized_copy(mid, last, finish);
- finish += n - elems_after;
- uninitialized_copy(position, old_finish, finish);
- finish += elems_after;
- copy(first, mid, position);
- }
- }
- else {
- const size_type old_size = size();
- const size_type len = old_size + max(old_size, n);
- iterator new_start = data_allocator::allocate(len);
- iterator new_finish = new_start;
- __STL_TRY {
- new_finish = uninitialized_copy(start, position, new_start);
- new_finish = uninitialized_copy(first, last, new_finish);
- new_finish = uninitialized_copy(position, finish, new_finish);
- }
- # ifdef __STL_USE_EXCEPTIONS
- catch(...) {
- destroy(new_start, new_finish);
- data_allocator::deallocate(new_start, len);
- throw;
- }
- # endif /* __STL_USE_EXCEPTIONS */
- destroy(start, finish);
- deallocate();
- start = new_start;
- finish = new_finish;
- end_of_storage = new_start + len;
- }
- }
- }
-
- #else /* __STL_MEMBER_TEMPLATES */
-
- template <class T, class Alloc>
- void vector
::insert(iterator position, - const_iterator first,
- const_iterator last) {
- if (first != last) {
- size_type n = 0;
- distance(first, last, n);
- if (size_type(end_of_storage - finish) >= n) {
- const size_type elems_after = finish - position;
- iterator old_finish = finish;
- if (elems_after > n) {
- uninitialized_copy(finish - n, finish, finish);
- finish += n;
- copy_backward(position, old_finish - n, old_finish);
- copy(first, last, position);
- }
- else {
- uninitialized_copy(first + elems_after, last, finish);
- finish += n - elems_after;
- uninitialized_copy(position, old_finish, finish);
- finish += elems_after;
- copy(first, first + elems_after, position);
- }
- }
- else {
- const size_type old_size = size();
- const size_type len = old_size + max(old_size, n);
- iterator new_start = data_allocator::allocate(len);
- iterator new_finish = new_start;
- __STL_TRY {
- new_finish = uninitialized_copy(start, position, new_start);
- new_finish = uninitialized_copy(first, last, new_finish);
- new_finish = uninitialized_copy(position, finish, new_finish);
- }
- # ifdef __STL_USE_EXCEPTIONS
- catch(...) {
- destroy(new_start, new_finish);
- data_allocator::deallocate(new_start, len);
- throw;
- }
- # endif /* __STL_USE_EXCEPTIONS */
- destroy(start, finish);
- deallocate();
- start = new_start;
- finish = new_finish;
- end_of_storage = new_start + len;
- }
- }
- }
-
- #endif /* __STL_MEMBER_TEMPLATES */
-
- #if defined(__sgi) && !defined(__GNUC__) && (_MIPS_SIM != _MIPS_SIM_ABI32)
- #pragma reset woff 1174
- #endif
-
- __STL_END_NAMESPACE
-
- #endif /* __SGI_STL_INTERNAL_VECTOR_H */
-
- // Local Variables:
- // mode:C++
- // End:
-
相关阅读:
4.2冰达机器人:视觉实例-机器人视觉循线、视觉实例-调整循线颜色
关于 Git 重写历史的一些笔记
计算机毕业设计 基于SSM的在线预约导游系统的设计与实现 Java实战项目 附源码+文档+视频讲解
Unity3d-异步加载场景、进度条加载
基于SSM的智慧城市实验室主页系统的设计与实现
spring中那些让你爱不释手的代码技巧(续集)
tcp滑动窗口原理
信钰证券:碧桂园大涨,石墨烯拉升
GBase 8c结果集类型
原子的核型结构及氢原子的波尔理论
-
原文地址:https://blog.csdn.net/weixin_62684026/article/details/126335773