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

用_start指向头,_finish指向最后一个元素的尾巴,_end指向最大容量。
- #include
- #include
-
- using namespace std;
-
- template<class T>
- 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); //插入这些值
- }
- }
- template<class iterator_begin, class iterator_end>
- Vector(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可以通过三个指针实现一个基本版。
要特别注意迭代器失效问题,这是和野指针问题一样的严重程序设计问题。