一、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 destroy vector() {} //构造一个长度为n,值为value的vector vector(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; } // capacity size_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; } }; }