接口一览
namespace My_STL
{
template<class T>
class vector
{
public:
// Vector的迭代器是一个原生指针
typedef T* iterator;
typedef const T* const_iterator;
iterator begin();
iterator end();
const_iterator cbegin();
const_iterator cend() const;
// construct and destroy
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();
// capacity
size_t size() const ;
size_t capacity() const;
void reserve(size_t n);
void resize(size_t n, const T& value = T());
///////////////access///////////////////////////////
T& operator[](size_t pos);
const T& operator[](size_t pos)const;
///////////////modify/////////////////////////////
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; // 指向存储容量的尾
};
}
构造函数
构造函数1
vector()
:_start(nullptr)
, _finish(nullptr)
, _endofstorage(nullptr)
{}
用迭代器区间初始化
template<class InputIterator>
vector(InputIterator first, InputIterator last)
{
while (first!=last)
{
push_back(*first);
++first;
}
}
n个val初始化
vector(size_t n, const T& val = T())
{
reserve(n);
for (size_t i = 0; i < n; i++)
{
push_back(val);
}
}
//针对int
vector(int n, const T& val = T())
{
reserve(n);
for (size_t i = 0; i < n; i++)
{
push_back(val);
}
}
析构函数
~vector()
{
delete[] _start;
_start = _finish = _endofstorage = nullptr;
}
拷贝构造函数
vector(const vector<T>& v)
{
reserve(v.capacity());
for (auto& e : v)
{
push_back(e);
}
}
运算符重载
=运算符
void swap(vector<T>& v)
{
std::swap(_start, v._start);
std::swap(_finish, v._finish);
std::swap(_endofstorage, v._endofstorage);
}
vector<T>& operator=(vector<T> tmp)
{
swap(tmp);
return *this;
}
[]运算符
T& operator[](size_t pos)
{
assert(pos < size());
return _start[pos];
}
const T& operator[](size_t pos)const
{
assert(pos < size());
return _start[pos];
}
reserve
功能分析
当n大于对象当前的capacity时,将capacity扩大。当n小于对象当前的capacity时,什么也不做
注意
不要使用memcpy函数拷贝数据,如果数据是内置类型或浅拷贝的自定义类型,使用memcpy是没有什么问题的,但如果数据是需要深拷贝的自定义类型(string),问题就出现了,会有浅拷贝的问题
void reserve(size_t n)
{
if (n > capacity())
{
T* tmp = new T[n];
size_t sz = size();
if (_start)
{
for (size_t i = 0; i < sz; i++)
{
tmp[i] = _start[i];
}
delete[] _start;
}
_start = tmp;
_finish = _start + sz;
_endofstorage = _start + n;
}
}
resize
功能分析
当 n < size 时,直接有效数据长度缩小。
当 size < n <= capacity 时,我们将有效数据的长度增加到 n,增加出来的有效数据内容是val。
当 n > capacity时,先调用上面的 reserve 函数进行增容,再将有效数据的长度增加到 n,增加出来的有效数据内容是val。
注意
由于不确定成员变量的类型,需要用匿名对象提供缺省值,并且因为匿名对象有常性,因此需要加上const
void resize(size_t n, const T& val = T())
{
if (n < size())
{
_finish = _start + n;
}
else
{
reserve(n);
while (_finish<_start+n)
{
*_finish = val;
_finish++;
}
}
}
push_back
尾插入数据,首先要检查是否已满,已满则进行增容,增容后尾插即可。也可以直接复用insert。
void push_back(const T& x)
{
/*if (_finish == _endofstorage)
{
size_t sz = size();
size_t cp = capacity() == 0 ? 4 : capacity() * 2;
T* tmp = new T[cp];
if (_start)
{
memcpy(tmp, _start, sizeof(T) * sz);
delete[] _start;
}
_start = tmp;
_finish = _start + sz;
_endofstorage = _start + cp;
}
*_finish = x;
_finish++;*/
insert(end(), x);
}
insert
当容量不够的时候,会发生扩容,这个时候_start等迭代器已经变换了位置,原来迭代器pos指向的位置已经失效,这个就是迭代器的内部失效,这个时候需要再扩容前记录下来pos和_start的相对位置,在扩容之后进行更新。并不是每一次扩容都会导致这个问题
void insert(iterator pos, const T& x)
{
assert(pos >= _start);
assert(pos <= _finish);
if (_finish == _endofstorage)
{
size_t len = pos - _start;
reserve(capacity() == 0 ? 4 : capacity() * 2);
pos = _start + len;
}
iterator end = _finish - 1;
while (end >= pos)
{
*(end + 1) = *end;
end--;
}
*pos = x;
_finish++;
}
erease
iterator erase(iterator pos)
{
assert(pos >= _start);
assert(pos <= _finish);
iterator it = pos + 1;
while (it < _finish)
{
*(it - 1) = *it;
it++;
}
_finish--;
return pos;
}
capacity
size_t capacity()const
{
return _endofstorage - _start;
}
size
size_t size()const
{
return _finish - _start;
}
全部代码
namespace My_STL
{
template<class T>
class vector
{
public:
typedef T* iterator;
typedef const T* const_iterator;
iterator begin()
{
return _start;
}
const_iterator begin()const
{
return _start;
}
iterator end()
{
return _finish;
}
const_iterator end()const
{
return _finish;
}
//vector()
// :_start(nullptr)
// , _finish(nullptr)
// , _endofstorage(nullptr)
//{}
//构造函数要写,下面会有缺省值,这里写了会进行初始化
vector()
{}
//用一个迭代器区间初始化,为了兼容各个类型,因此使用模板
template<class InputIterator>
vector(InputIterator first, InputIterator last)
{
while (first!=last)
{
push_back(*first);
++first;
}
}
//n个val初始化
vector(size_t n, const T& val = T())
{
reserve(n);
for (size_t i = 0; i < n; i++)
{
push_back(val);
}
}
vector(int n, const T& val = T())
{
reserve(n);
for (size_t i = 0; i < n; i++)
{
push_back(val);
}
}
//拷贝构造v2(v1)
vector(const vector<T>& v)
{
reserve(v.capacity());
for (auto& e : v)
{
push_back(e);
}
}
void swap(vector<T>& v)
{
std::swap(_start, v._start);
std::swap(_finish, v._finish);
std::swap(_endofstorage, v._endofstorage);
}
vector<T>& operator=(vector<T> tmp)
{
swap(tmp);
return *this;
}
~vector()
{
delete[] _start;
_start = _finish = _endofstorage = nullptr;
}
void reserve(size_t n)
{
if (n > capacity())
{
T* tmp = new T[n];
size_t sz = size();
if (_start)
{
//memcpy(tmp, _start, sizeof(T) * sz);
for (size_t i = 0; i < sz; i++)
{
tmp[i] = _start[i];
}
delete[] _start;
}
_start = tmp;
_finish = _start + sz;
_endofstorage = _start + n;
}
}
void resize(size_t n, const T& val = T())
//由于不确定vector成员变量的类型,因此在给缺省值的时候不能给一个具体的值,可以用一个匿名对象来初始化
// 因为匿名对象有常性,因此必须加上const
//const会延长变量的作用域,会一直延长到val消失
//这里可以认为内置类型也有构造函数,这个是为了让逻辑更通恰
{
if (n < size())
{
_finish = _start + n;
}
else
{
reserve(n);
while (_finish<_start+n)
{
*_finish = val;
_finish++;
}
}
}
void push_back(const T& x)
{
/*if (_finish == _endofstorage)
{
size_t sz = size();
size_t cp = capacity() == 0 ? 4 : capacity() * 2;
T* tmp = new T[cp];
if (_start)
{
memcpy(tmp, _start, sizeof(T) * sz);
delete[] _start;
}
_start = tmp;
_finish = _start + sz;
_endofstorage = _start + cp;
}
*_finish = x;
_finish++;*/
insert(end(), x);
}
void insert(iterator pos, const T& x)
{
assert(pos >= _start);
assert(pos <= _finish);
if (_finish == _endofstorage)
{
size_t len = pos - _start;
//由于发生扩容,迭代器pos内部失效,因为_start到了新的空间,而原来的迭代器还指向原来的空间。
//这里计算出相对距离,更新pos
reserve(capacity() == 0 ? 4 : capacity() * 2);
pos = _start + len;
}
iterator end = _finish - 1;
while (end >= pos)
{
*(end + 1) = *end;
end--;
}
*pos = x;
_finish++;
}
iterator erase(iterator pos)
{
assert(pos >= _start);
assert(pos <= _finish);
iterator it = pos + 1;
while (it < _finish)
{
*(it - 1) = *it;
it++;
}
_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];
}
size_t capacity()const
{
return _endofstorage - _start;
}
size_t size()const
{
return _finish - _start;
}
private:
iterator _start = nullptr;
iterator _finish = nullptr;
iterator _endofstorage = nullptr;
};
}
本文详细介绍了C++标准模板库(STL)中的vector类,包括其构造方法、迭代器使用、容量管理(reserve和resize)、元素添加(push_back和insert)以及元素删除(erase)。
4010





