本章代码gitee仓库:vector模拟实现、vector源码
文章目录
- 😈0. 搭个框架
- 😄1. 成员
- 👻2. 构造函数 & 析构函数 & 拷贝构造
- 😺3. 迭代器
- 🙉4. operator[] & operator=
- 🤖5. 容器的容量 & 个数
- 👾6. 扩容
- 👿7. 插入 & 删除操作
😈0. 搭个框架
#include<iostream>
#include<vector>
#include<string>
#include<assert.h>
using std::cout;
using std::endl;
namespace myvector
{
template<typename T>
class vector
{
public:
typedef T* iterator;
typedef const T* const_iterator;
private:
}
//代码测试区
void t1(){}
//...
}
😄1. 成员
看源码发现vector
是类模板定义的,成员是采用迭代器进行管理
iterator _start; //初始位置
iterator _finish; //结束位置
iterator _end_of_storage; //容量
👻2. 构造函数 & 析构函数 & 拷贝构造
当涉及到容器类时,通常有一些关键函数,如构造函数、析构函数和拷贝构造函数,它们负责初始化容器对象、销毁对象和进行对象的拷贝等
这里注意拷贝构造要实现的是深拷贝
vector()
:_start(nullptr)
, _finish(nullptr)
, _end_of_storage(nullptr)
{}
vector(size_t n, const T& val=T())
:_start(nullptr)
, _finish(nullptr)
, _end_of_storage(nullptr)
{
resize(n, val);
}
//有选择
vector(int n, const T& val = T())
:_start(nullptr)
, _finish(nullptr)
, _end_of_storage(nullptr)
{
resize(n, val);
}
//拷贝构造
vector(const vector<T>& v)
:_start(nullptr)
, _finish(nullptr)
, _end_of_storage(nullptr)
{
size_t vSize = v.size();
if (vSize > 0)
{
_start = new T[vSize];
//深拷贝
for (size_t i = 0; i < vSize; i++)
{
_start[i] = v._start[i];
}
_finish = _start + vSize;
_end_of_storage = _start + vSize;
}
}
//迭代器初始化
template<typename InpuIterator>
vector(InpuIterator first, InpuIterator last)
:_start(nullptr)
, _finish(nullptr)
, _end_of_storage(nullptr)
{
while (first != last)
{
push_back(*first);
++first;
}
}
//析构
~vector()
{
if (_start)
{
delete[] _start;
_start = _finish = _end_of_storage = nullptr;
}
}
😺3. 迭代器
加上const
,兼容具有常属性的元素
iterator begin()
{
return _start;
}
iterator end()
{
return _finish;
}
const const_iterator begin() const
{
return _start;
}
const const_iterator end() const
{
return _finish;
}
🙉4. operator[] & operator=
重载[]操作符
,下标访问,方便查看
重载=操作符
,用于将当前容器对象赋值为另一个容器对象
当执行容器的深拷贝时(例如使用赋值运算符 =),会创建一个新的独立的容器,并复制原始容器的元素到新容器中。
在深拷贝过程中,原始容器和新容器中的元素是独立的,它们有各自的内存空间。
深拷贝可以防止两个容器共享相同的元素内存,从而避免了一个容器修改元素影响另一个容器的问题。
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 swap(vector<T>& v)
{
std::swap(_start, v._start);
std::swap(_finish, v._finish);
std::swap(_end_of_storage, v._end_of_storage);
}
vector<T>& operator=(vector<T> v)
{
swap(v);
return *this;
}
🤖5. 容器的容量 & 个数
size_t capacity() const
{
return _end_of_storage - begin();
}
size_t size() const
{
return _finish - _start;
}
👾6. 扩容
void reserve(size_t n)
{
if (capacity() < n)
{
const size_t old_size = size();
iterator tmp = new T[n];
// _start不为空挪数据
if (_start)
{
//实现深拷贝
//memcpy(tmp, _start, sizeof(T) * old_size);
for (size_t i = 0; i < old_size; ++i)
{
tmp[i] = _start[i];
}
delete[] _start;
}
_start = tmp;
_finish = tmp + old_size;
_end_of_storage = _start + n;
}
}
void resize(size_t new_size, const T& x = T())
{
if (new_size < size())
_finish = _start + new_size;
else
{
reserve(new_size);
while (_finish != _start + new_size)
{
*_finish = x;
++_finish;
}
}
}
👿7. 插入 & 删除操作
指定位置插入/删除时,要注意迭代器失效的问题,采用iterator
为返回类型,可以接收修改后的位置
迭代器失效:
在对容器进行插入和删除操作时,特别是涉及重新分配内存的情况下,会导致迭代器失效。
插入元素可能导致插入位置之后的元素迭代器失效,而删除元素可能导致删除位置之后的元素迭代器失效。
一旦迭代器失效,对其进行解引用或使用会导致未定义的行为
void push_back(const T& x)
{
insert(end(), x);
/*if (_finish == _end_of_storage)
{
reserve(capacity() == 0 ? 4 : 2 * capacity());
}
*_finish = x;
_finish++;*/
}
void pop_back()
{
--_finish;
}
iterator insert(iterator pos, const T& x)
{
assert(pos >= _start && pos <= _finish);
if (_finish == _end_of_storage)
{
size_t n = pos - begin();
reserve(capacity() == 0 ? 4 : 2 * capacity());
pos = begin() + n;
}
iterator end = _finish - 1;
while (pos <= end)
{
*(end + 1) = *end;
--end;
}
*pos = x;
++_finish;
return pos;
}
iterator erase(iterator pos)
{
assert(pos >= _start && pos < _finish);
if (pos+1 != _finish)
{
iterator it = pos + 1;
while (it != _finish)
{
*(it-1) = *it;
++it;
}
}
--_finish;
return pos;
}
这里还是要注意深浅拷贝,自定义类型一定是要进行深拷贝的。
那么本期的分享就到这里,我们下期再见,如果还有下期的话。