这次选择直接展示相关接口实现,但是在此之前,需要先了解一下vector的底层实现。
一、底层实现
vector底层存的是三个迭代器(本质是指针T*,T是模版参数,代表类型)
1._start(指向第一个元素)
2._finish(指向最后一个元素的下一个元素)
3._end_of_storage(指向最大容量的下一个元素)
下面展示vector的大体框架
template <class T>
class Vector{
public:
typedef T* iterator;//普通迭代器
typedef const T* const_iterator;//const迭代器
public:
//迭代器 -- 指向第一个元素
iterator begin();
//迭代器 -- 指向最后一个元素的下一个
iterator end();
//const迭代器 -- 指向第一个元素
const_iterator begin() const;
//const迭代器 -- 指向最后一个元素的下一个
const_iterator end() const;
//构造函数
Vector();
//析构函数
~Vector();
//拷贝构造 v2(v1)
Vector(const Vector<T>& v);
//交换函数(用于深拷贝的现代写法)
void swap(Vector<T>& v);
//operator=
Vector<T>& operator=(const Vector<T>& v);
//数据个数
size_t size() const;
//当前容量
size_t capacity() const;
//将容量扩大到n
void reserve(size_t n);
//修改size
void resize(size_t n, const T& x = T());
//尾插单个元素
void push_back(const T& x);
//尾删单个元素
void pop_back();
//pos位置插入
void insert(iterator pos, const T& x);
//pos位置删除
iterator easer(iterator pos);
//普通对象的operator[]
T& operator[](size_t i);
//const对象的operator[]
const T& operator[](size_t i) const;
private:
iterator _start;//指向第一个元素
iterator _finish;//指向最后一个元素的下一个
iterator _end_of_storage;//指向最大容量的下一个
};
二、相关接口
(一)迭代器
1.普通迭代器
适用于普通对象
//迭代器 -- 指向第一个元素
iterator begin()
{
return _start;
}
//迭代器 -- 指向最后一个元素的下一个
iterator end()
{
return _finish;
}
2.const迭代器
适用于const对象
//const迭代器 -- 指向第一个元素
const_iterator begin() const
{
return _start;
}
//const迭代器 -- 指向最后一个元素的下一个
const_iterator end() const
{
return _finish;
}
(二)默认成员函数
1.构造函数
//构造函数
Vector()
:_start(nullptr)
,_finish(nullptr)
,_end_of_storage(nullptr)
{}
2.析构函数
~Vector()
{
delete[] _start;
_start = _finish = _end_of_storage = nullptr;
}
3.拷贝构造
//拷贝构造 this(v)
//把this改造的和v一模一样
Vector(const Vector<T>& v)
//将this初始化
:_start(nullptr)
,_finish(nullptr)
,_end_of_storage(nullptr)
{
reserve(v.capacity());//直接开辟出所需空间大小,减少扩容带来的消耗
for(const auto& e:v)
push_back(e);//将v中每个元素依次尾插到this上
}
4.operator=
void swap(Vector<T>& v)
{
::swap(_start,v._start);//加::是为了调用库里的swap函数
::swap(_finish,v._finish);
::swap(_end_of_storage, v._end_of_storage);
}
Vector<T>& operator=(const Vector<T>& v)
{
Vector<T> tmp(v);
swap(tmp);//v和this交换
return *this;
}
(三)capacity
1.数据个数 size_t size() const
//数据个数
size_t size() const
{
return _finish - _start;//指针减指针
}
2.当前容量 size_t capacity() const
//当前容量
size_t capacity() const
{
return _end_of_storage - _start;//指针减指针
}
3.将容量扩大到n void reserve(size_t n)
注意⚠️:将原数组的数据拷贝到新数组时,要进行深拷贝
如果使用memcpy进行拷贝 -> 只是按字节拷贝(浅拷贝),会产生问题
正确的做法:使用operator= 进行深拷贝 -> 这样就可以实现vector<string>这类对象
//将容量扩大到n
void reserve(size_t n)
{
//只能扩大,不能缩小
if(n > capacity())
{
size_t oldSize = size();
T* tmp = new T[n];
//将原来的数据拷贝到新数组
//注意原数组有数据才拷贝过去
if(_start != nullptr)
{
//拷贝(⚠️一定要深拷贝,使用operator=就是深拷贝)
for(size_t i=0; i<oldSize; i++)
{
tmp[i] = _start[i];//深拷贝
}
delete[] _start;//不为空才释放
}
//修改三个成员变量
_start = tmp;
_finish = tmp + oldSize;
_end_of_storage = tmp + n;
}
}
4.将当前size修改成n void resize(size_t n, const T& x = T())
注意⚠️:T()就相当于int中的0,char中的'\0'
void resize(size_t n, const T& x = T())
{
//缩小,直接改
if(n < size())
{
_finish = _start + n;
}
//扩大
else
{
//先扩容
if(n > capacity())
reserve(n);
//在补x
for(size_t i=size(); i<n; i++)
{
_start[i] = x;
}
//改结束标志
_finish = _start + n;
}
}
(四)插入删除
1.尾插单个元素 void push_back(const T& x)
//尾插单个元素
void push_back(const T& x)
{
//先扩容
if(_finish == _end_of_storage)
{
size_t newcapacity = capacity() == 0 ? 4 : capacity() * 2;
reserve(newcapacity);
}
//在尾插
*_finish = x;
_finish++;
}
2.尾删单个元素 void pop_back()
void pop_back()
{
assert(_start < _finish);//防止一个都没有,还删除,就不对了
_finish--;
}
3.pos位置插入 void insert(iterator pos, const T& x)
注意⚠️:因为传过来的pos是指向原数组的,但是如果要扩容,原数组被释放,pos就变成了野
指针。所以我们需要将pos指向新数组的对应位置。
void insert(iterator pos, const T& x)
{
assert(pos <= _finish);//加=是为了支持尾插
//扩容
if(_finish == _end_of_storage)
{
//记录开始到pos的距离
size_t n = pos - _start;
//扩容
size_t newcapacity = capacity() == 0 ? 4 : capacity() * 2;
reserve(newcapacity);
//处理迭代器失效
//传过来的pos是指向原来数组的,但是扩容以后原来的数组被释放掉了
//需要将pos指向新的数组
pos = _start + n;
}
//挪数据
iterator end = _finish - 1;
while (end >= pos)
{
*(end + 1) = *end;
end--;
}
//插入
*pos = x;
_finish++;
}
4.pos位置删除 iterator easer(iterator pos)
注意⚠️:删除会返回一个迭代器,并且返回的迭代器指向被删除的元素的下一个
iterator easer(iterator pos)
{
assert(pos < _finish);
//挪数据
iterator it = pos;
while (it < _finish) {
*it = *(it + 1);
it++;
}
//改
_finish--;
//返回被删元素的下一个的位置
return pos;
}
(五)operator[]
1.普通对象使用
T& operator[](size_t i)
{
assert(i < size());
return _start[i];
}
2.const对象使用
const T& operator[](size_t i) const
{
assert(i < size());
return _start[i];
}