文章目录
vector 模拟实现
vector介绍
vector是表示可变大小数组的序列容器
就像数组一样,vector也采用连续的存储空间来存储元素。也就是意味着可以采用下标对vector的元素进行访问,和数组一样高效。但是又不像数组,它的大小是可以动态改变的,而且它的大小会被容器自动处理。
vector 基本框架
namespace my_vector
{
template<class T>
class vector
{
public:
typedef T* iterator;
typedef const T* const_iterator;
iterator begin();
iterator end();
const_iterator cbegin();
const_iterator cend() const;
vector();
vector(int n, const T& value = T());
template<class InputIterator>
vector(InputIterator first, InputIterator last);
vector(const vector<T>& v);
vector<T>& operator= (vector<T> v);
~vector();
size_t size() const;
size_t capacity() const;
void reserve(size_t n);
void resize(size_t n, const T& value = T());
T& operator[](size_t pos);
const T& operator[](size_t pos)const;
void push_back(const T& x);
void pop_back();
void swap(vector<T>& v);
iterator insert(iterator pos, const T& x);
iterator erase(Iterator pos);
private:
iterator _start; // 指向数据块的开始
iterator _finish; // 指向有效数据的尾
iterator _endOfStorage; // 指向存储容量的尾
};
}
默认成员函数
构造函数
构造一个空vector,size 和 capacity 为 0,将 _start,_finish, _endofstorage 都置为空指针即可
vector() :_start(nullptr), _finish(nullptr), _endofStorage(nullptr) {}
用n个 val 值进行初始化,可以复用 resize 接口,但要注意调用resize()接口需要计size(),capacity(),所以要将成员变量进行初始化
vector(int n, const T& value = T())
{
resize(n, value);
}
用迭代器区间进行初始化,由于不同类型的容器迭代器类型不同,设计成函数模板,将区间内的内容尾插入vector即可,但注意调用push_back接口通过 _finish == _endofstorage 判断是否满,需要初始化
//迭代器
template<class InputIterator>
vector(InputIterator first, InputIterator last)
{
reserve(last - first);
while (first != last)
{
*_finish++ = *first++;
}
}
拷贝构造函数
vector(const vector<T>& v)
{
reserve(v.capacity());
T* first = v._start;
while (first != v._finish)
{
*_finish++ = *first++;
}
}
赋值构造函数
vector<T>& operator= (vector<T> v)
{
swap(v);
return *this;
}
析构函数
~vector()
{
if (_start)
delete[]_start;
_start = nullptr;
_finish = nullptr;
_endofStorage = nullptr;
}
扩容操作
reserve()
- n >= capacity,将capacity扩大到n或大于n。
- n < capacity,直接出函数
void reserve(size_t n)
{
if (n > capacity())
{
T* tmp = new T[n];
size_t num = size();
if (_start)
{
for (size_t i = 0; i < num; i++)
{
tmp[i] = _start[i];
}
delete[] _start;
}
_start = tmp;
_finish = _start + num;
_endofStorage = _start + n;
}
}
实现步骤:
- 新开辟一块空间,若容器为空,将_start,_finish指向新开辟空间的首元素地址, _endofstorage指向新开辟空间的最后一个元素下一个位置
- 若容器不为空,将数据拷贝到新空间,释放掉旧空间,更新_start,_finish, _endofstorage的位置
注意 : 将数据拷贝到新空间,不能用memcpy,使用memcpy函数以后,新开辟空间里的元素和原空间里的元素所指向的内存空间是一样的,当旧空间被释放时,会调用自定义类型的析构函数,从而使得新开辟空间里的元素指向的内存空间也被释放掉了
resize()
- n < size : 直接将 _finish = _start + n (将有效数据长度缩小)即可
- size < n <= capacity :我们将有效数据的长度增加到 n,增加出来的有效数据内容是val
- n > capacity : 先调用上面的 reserve 函数进行增容,再将有效数据的长度增加到 n,增加出来的有效数据内容是val。
void resize(size_t n, const T& value = T())
{
size_t num = size();
if (n > num)
{
reserve(n);
for (size_t i = num; i < n; i++)
{
_start[i] = value;
}
}
_finish = _start + n;
}
尾插&尾删
push_back
- 尾插入数据,首先要检查是否已满
void push_back(const T& x)
{
if (size() == capacity())
reserve(capacity() == 0 ? 4 : capacity() * 2);
*_finish++ = x;
}
pop_back
- 尾删时,首先判断容器是否为空
void pop_back()
{
if (size() > 0)
_finish--;
}
插入
insert()
- 容量不够,先增容,增容之前先记录下 pos - _start 的值,否则增容之后,pos 还指向原来已经被释放的空间
- 将 pos 位置往后的数据往后挪动一位,在pos位置插入值val
iterator insert(iterator pos, const T& x)
{
assert(pos >= _start && pos <= _finish);
if (_finish == _endofStorage)
reserve(capacity() == 0 ? 4 : capacity() * 2);
T* finish = _finish;
while (finish > pos)
{
*finish = *(finish - 1);
finish--;
}
*pos = x;
_finish++;
return pos;
}
删除
erase()
容器若为空,则做断言处理,若不为空,将pos位置往后的数据向前挪动一位
iterator erase(iterator pos)
{
assert(pos >= 0 && pos < _finish);
T* _pos = pos;
while (_pos < _finish - 1)
{
*_pos = *(_pos + 1);
_pos++;
}
_finish--;
return pos;
}
运算符重载
T& operator[](size_t pos)
{
assert(pos < size());
return _start[pos];
}
const T& operator[](size_t pos)const
{
assert(pos < size());
return _start[pos];
}
迭代器
begin()返回第一个元素的地址,end()返回最后一个元素下一位置的地址;
非const 迭代器
iterator begin()
{
return _start;
}
iterator end()
{
return _finish;
}
const 迭代器
为了让const对象调用,加入const版本的begin()和end();
const_iterator cbegin()
{
return _start;
}
const_iterator cend() const
{
return _finish;
}
其他辅助函数
size()
返回容器中有效数据的个数
size_t size() const
{
return _finish - _start;
}
capacity()
返回容器的容量
size_t capacity() const
{
return _endofStorage - _start;
}
void swap(vector<T>& v)
{
T* tmp = v._start;
v._start = _start;
_start = tmp;
tmp = v._finish;
v._finish = _finish;
_finish = tmp;
tmp = v._endofStorage;
v._endofStorage = _endofStorage;
_endofStorage = tmp;
}
代码总览
#include<iostream>
#include<assert.h>
using std::cout;
using std::cin;
using std::endl;
namespace my_vector
{
template<class T>
class vector
{
private:
typedef T* iterator;
iterator _start; // 指向数据块的开始
iterator _finish; // 指向有效数据的尾
iterator _endofStorage; // 指向存储容量的尾
public:
typedef T* iterator;
typedef const T* const_iterator;
iterator begin()
{
return _start;
}
iterator end()
{
return _finish;
}
const_iterator cbegin()
{
return _start;
}
const_iterator cend() const
{
return _finish;
}
vector() :_start(nullptr), _finish(nullptr), _endofStorage(nullptr) {}
vector(int n, const T& value = T())
{
resize(n, value);
}
template<class InputIterator>
vector(InputIterator first, InputIterator last)
{
reserve(last - first);
while (first != last)
{
*_finish++ = *first++;
}
}
vector(const vector<T>& v)
{
reserve(v.capacity());
T* first = v._start;
while (first != v._finish)
{
*_finish++ = *first++;
}
}
vector<T>& operator= (vector<T> v)
{
swap(v);
return *this;
}
~vector()
{
if (_start)
delete[]_start;
_start = nullptr;
_finish = nullptr;
_endofStorage = nullptr;
}
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];
size_t num = size();
if (_start)
{
for (size_t i = 0; i < num; i++)
{
tmp[i] = _start[i];
}
delete[] _start;
}
_start = tmp;
_finish = _start + num;
_endofStorage = _start + n;
}
}
void resize(size_t n, const T& value = T())
{
size_t num = size();
if (n > num)
{
reserve(n);
for (size_t i = num; i < n; i++)
{
_start[i] = value;
}
}
_finish = _start + n;
}
T& operator[](size_t pos)
{
assert(pos < size());
return _start[pos];
}
const T& operator[](size_t pos)const
{
assert(pos < size());
return _start[pos];
}
void push_back(const T& x)
{
if (size() == capacity())
reserve(capacity() == 0 ? 4 : capacity() * 2);
*_finish++ = x;
}
void pop_back()
{
if (size() > 0)
_finish--;
}
void swap(vector<T>& v)
{
T* tmp = v._start;
v._start = _start;
_start = tmp;
tmp = v._finish;
v._finish = _finish;
_finish = tmp;
tmp = v._endofStorage;
v._endofStorage = _endofStorage;
_endofStorage = tmp;
}
iterator insert(iterator pos, const T& x)
{
assert(pos >= _start && pos <= _finish);
if (_finish == _endofStorage)
reserve(capacity() == 0 ? 4 : capacity() * 2);
T* finish = _finish;
while (finish > pos)
{
*finish = *(finish - 1);
finish--;
}
*pos = x;
_finish++;
return pos;
}
iterator erase(iterator pos)
{
assert(pos >= 0 && pos < _finish);
T* _pos = pos;
while (_pos < _finish - 1)
{
*_pos = *(_pos + 1);
_pos++;
}
_finish--;
return pos;
}
};
}
using namespace my_vector;
int main()
{
vector<int> ret;
for(int i=0;i<100;i++)
ret.push_back(i);
vector<int> ret1 = ret;
//vector<int> ret2(100,3);
vector<int> res(ret.begin(), ret.end());
for (int i=0;i<20;i++)
{
ret1.insert(ret1.begin(),2000);
}
for (auto e : ret1)
{
cout << e << " ";
}
}