目录
1.vector的模拟实现
2.迭代器失效问题
3.总结
这里,我们使用三个指针来控制vector。

用_start指向头,_finish指向最后一个元素的尾巴,_end指向最大容量。
#include
#includeusing namespace std;template
class Vector
{
public:typedef T* iterator; //将原生指针模拟成迭代器typedef const T* const_iterator; //给一个const版本Vector():_start(nullptr), _finish(nullptr), _end(nullptr){}Vector(int n, const T& t = T()) :_start(nullptr), _finish(nullptr), _end(nullptr){reverse(n); //先开n个空间for (int i = 0; i < n; i++){push_back(t); //插入这些值}}templateVector(iterator_begin begin, iterator_end end) //迭代器初始化版:_start(nullptr), _finish(nullptr), _end(nullptr){while (begin != end){push_back(*begin);begin++;}}void swap(Vector& v){std::swap(_start, v._start);std::swap(_finish, v._finish);std::swap(_end, v._end);}Vector(Vector& v) //现代写法:_start(nullptr), _finish(nullptr), _end(nullptr){Vector temp(v.begin(), v.end()); //先构造一个传入的拷贝swap(temp); //再交换}Vector& operator=(Vector t) //现代写法{swap(t); //因为t是传值,会发生拷贝。return *this;}iterator begin(){return _start;}iterator end(){return _finish;}const_iterator begin() const{return _start;}const_iterator end() const{return _finish;}~Vector() //析构函数{delete[] _start;_start = _finish = _end;}size_t capacity(){return _end - _start;}size_t size(){return _finish - _start;}T& operator[](size_t pos){assert(pos < size());return _start[pos];}void reverse(size_t n){if (n > capacity()){int sz = size();T* temp = new T[n];if (_start) //保证非空{for (int i = 0; i < sz; i++){temp[i] = _start[i];}delete _start;}_start = temp;_finish = _start + sz;_end = _start + n;}}void resize(size_t n, const T& val){if(n > capacity())reverse(n);if (n > size()){while (_finish < _start + n){*_finish = val;++_finish;}}else{_finish = _start + n;}}void pop_back(){assert(_finish > _start);--_finish;}iterator insert(iterator pos, const T& val){assert(pos >= _start);assert(pos <= _finish);if (_finish == _end) //满了{int len = pos - _start; //标记长度,不然下面找不到了。reverse(capacity() == 0 ? 4 : capacity() * 2);//非0开出2倍的空间pos = _start + len; }iterator cur = _finish-1; //因为finish会指向最后一个元素的尾部while (cur >= pos) //从最后一个位置向后移动{*(cur + 1) = *cur;--cur;}++_finish;*pos = val; return pos;}void push_back(const T& t){iterator temp = insert(end(), t); //复用插入}iterator erase(iterator pos) //返回删除位置下一个的迭代器{assert(pos >= _start);assert(pos <= _finish);iterator cur = pos + 1;while (cur < _finish){*(cur - 1) = *cur; //挪动数据++cur;}--_finish;return pos;}T& front(){assert(size() > 0);return *_start;}T& back(){assert(size() > 0);return *(_finish - 1);}private:iterator _start;iterator _finish;iterator _end;
};
需要注意的是:我们一般在拷贝构造或者扩容时会采用现代(托管+交换)的写法。
reverse:会新开一个大小n的空间,再将原来的的值拿过来。
拷贝构造:直接调用构造函数构造一个和传入的对象一样的实例,最后和this交换。
与传统的原地处理不同的是,这种方式会创造一个临时变量来托管处理,最后再交换。
对于vector迭代器的失效主要分为两种情况:
a.扩容导致的野指针

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

以删除元素为例,删除2以后,pos就指向了3。pos指向内容发生了突然变化,这时也就发生了迭代器的失效,pos失去了作用。
vector可以通过三个指针实现一个基本版。
要特别注意迭代器失效问题,这是和野指针问题一样的严重程序设计问题。
上一篇:C++11新标准