一、vector的简单认识
vector是表示可变大小数组的序列容器。 就像数组一样,vector也采用的连续存储空间来存储元素。也就是意味着可以采用下标对vector的元素 进行访问,和数组一样高效。但是又不像数组,它的大小是可以动态改变的,而且它的大小会被容器自动处理。vector会分配一些额外的空间以适应可能的增长,因为存储空间比实际需要的存 储空间更大。不同的库采用不同的策略权衡空间的使用和重新分配。但是无论如何,重新分配都应该是对数增长的间隔大小,以至于在末尾插入一个元素的时候是在常数时间的复杂度完成的。与其它动态序列容器相比(deque, list and forward_list), vector在访问元素的时候更加高效,在末 尾添加和删除元素相对高效。对于其它不在末尾的删除和插入操作,效率更低。
二、vector的简单模拟实现
vector的底层我模仿库里面的实现方法,设计了三个指针:
class vector{public:typedef T* iterator;private:iterator _start; // 指向数据块的开始iterator _finish; // 指向有效数据的尾iterator _endOfStorage; // 指向存储容量的尾}
以及正向迭代器,不可修改迭代器,各种构造函数,析构函数, reserve(预开辟出空间,字符串还是原来的大小(一般不缩容)),resize(将vector设定为指定大小,字符串占满所开辟的空间),push_back(尾插),pop_back(尾删),insert(在pos位置上插入x,并返回pos位置的地址),erase(删除pos位置上的元素,并返回该位置的地址)。
注意事项:迭代器失效
以reserve为例,当reserve开辟新空间时会释放原来的旧空间,导致_start,_finish都不是原来的_start,_finish,如果此时贸然对_start,_finish进行运算,很可能会导致程序崩溃。我的做法是先记录下原来vector的长度,再用_start加上记录下的长度,就能得到正确的_finish,具体实现见下面代码。
完整代码
#pragma once
#include <iostream>
using namespace std;namespace sxb
{template<class T>class vector{public:typedef T* iterator;private:iterator _start; // 指向数据块的开始iterator _finish; // 指向有效数据的尾iterator _endOfStorage; // 指向存储容量的尾public:// Vector的迭代器是一个原生指针typedef const T* const_iterator;iterator begin(){return _start;}iterator end(){return _finish;}const_iterator cbegin() const{return _start;}const_iterator cend() const{return _finish;}// construct and destroyvector() {}//构造一个长度为n,值为value的vectorvector(int n, const T& value = T()){_start = new T[n+1];_finish = _start + n;_endOfStorage = _start + n;for (int i = 0; i < n; i++){*(_start + i) = value;}}template<class InputIterator>//利用一段迭代器构造vector(InputIterator first, InputIterator last){int len = 0;while (first != last)// 1 2 3 4 5{len++;first++;}len++;_start = new T[len+1];memcpy(_start, first, sizeof(T) * len);_finish = _start + len;_endOfStorage = _finish;}//利用已有的vector构造vector(const vector<T>& v){_start = new T[v.size() + 1];memcpy(_start, v.cbegin(), sizeof(T) * v.size());_finish = _start + v.size();_endOfStorage = _finish;}//赋值构造vector<T>& operator= (vector<T> v){vector(v);return *this;}~vector(){delete[] _start;_finish = nullptr;_endOfStorage = nullptr;}// capacitysize_t size() const{return _finish - _start;}size_t capacity() const{return _endOfStorage - _start;}void reserve(size_t n){if (n > capacity()){T* tmp = new T[n + 1];//迭代器失效处理int oldnum = _finish - _start;memcpy(tmp, _start, sizeof(T) * (_finish - _start));delete[] _start;_start = tmp;_finish = _start + oldnum;_endOfStorage = _start + n;}}void resize(size_t n, const T& value = T()){if (n > capacity()){int oldnum = _finish - _start;reserve(n);while ((_start + oldnum) != _endOfStorage){*(_start + oldnum) = value;oldnum++;}}else{_finish = _start + n;}}///access///T& operator[](size_t pos){return *(_start + pos);}const T& operator[](size_t pos)const{return *(_start + pos);}///modify/void push_back(const T& x){if (size() == capacity()){reserve(capacity() == 0 ? 4 : capacity() * 2);}_start[size()] = x;_finish++;}void pop_back(){_finish--;}void swap(vector<T>& v){std::swap(_start, v._start);std::swap(_finish, v._finish);std::swap(_endOfStorage, v._endOfStorage);}//迭代器失效iterator insert(iterator pos, const T& x){int len = 0;while (pos != _start){len++;pos--;}if (size() == capacity()){reserve(capacity() == 0 ? 4 : capacity() * 2);}iterator endfinish = _finish;while (endfinish > _start + len){*(endfinish) = *(endfinish - 1);endfinish--;}*endfinish = x;_finish++;return _start + len;}iterator erase(iterator pos){iterator pos2 = pos;while (pos != _finish - 1){*pos = *(pos + 1);pos++;}_finish--;return pos2;}};}