一、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;
}
};
}