1. insert()
这个就是在指定位置插入一个元素,首先计算要插入的这个位置和开头之间的距离,接着判断那个_finish 有没有碰到_endofstorage 或者_endofstorage 是不是为0,如果满足条件,那就进行扩容,然后接着重新计算距离,因为我们经过扩容了,所以可能插入的位置会不准,所以要重新计算,接着我们算一个end,这个end就是最后一个元素的位置,然后通过挪动的方式留出pos的空间,接着插入对应元素再++_finish 。
cpp
void insert(iterator pos, const T& x)
{
assert(pos >= _start && pos <= _finish);
size_t len = pos - _start;
if (_finish == _endofstorage && _endofstorage != 0)
{
reserve(capacity() * 2);
}
else
{
reserve(4);
}
pos = _start + len;
iterator end = _finish - 1;
while (end >= pos)
{
*(end + 1) = *end;
--end;
}
*pos = x;
++_finish;
}
2. reserve()
这个函数就是改变vector的capacity,同时并不像resize一样会添加或者减少元素。
首先保存当前元素数量 sz,然后动态分配大小为 n 的新内存 tmp。若原内存_start 非空,则通过循环调用元素的赋值运算符将原数据逐个复制到新内存中(而非直接使用 memcpy,避免浅拷贝问题),随后释放原内存。最后更新_start 指向新内存,_finish 指向原元素末尾的下一个位置,_endofstorage 指向新容量的末尾。若 n 不大于当前容量,则不执行任何操作。
简单来说就是新开一个扩容后数组然后把旧的赋值给他,接着直接把原来的vector的三个指针直接指向新的,从而完成替换实现reserve。
cpp
void reserve(size_t n)
{
if (n > capacity())
{
size_t sz = size();
T* tmp = new T[n];
if (_start)
{
//memcpy(tmp, _start, sizeof(T) * sz);
for (int i = 0; i < sz; i++)
{
tmp[i] = _start[i];
}
delete[] _start;
}
_start = tmp;
_finish = _start + sz;
_endofstorage = _start + n;
}
}
3. resize()
这个函数就是改变vector的大小,如果比原来的size小,那就改变finish的位置。
如果比原来的size大,那就吧finish向后移动,并在每一个添加的位置赋值为val。
PS:这个val之所以要设计成const T& val=T(),是因为我们并不知道这个vector里面是什么类型的,在加上这个resize在stl库里面支持只给一个n,所以我们在这里就这么设计。意思是表用它的默认构造,我们在这里不用担心int这种内置类型,因为C++支持像int a=int(1)这种语法了。
cpp
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;
}
}
}
4. swap()
这个的话就是交换两个vetcor里面的内容。
原理上来说的话就是通过swap两个vector里面的三个指针来实现。
cpp
void swap(vector<T>& v)
{
std::swap(_start, v._start);
std::swap(_finish, v._finish);
std::swap(_endofstorage, v._endofstorage);
}
5. capacity()
这个的话就是返回vector的capacity,因为_endofstorage和_start是指针而不是实际的大小,所以我们在这里要做减法。
cpp
size_t capacity() const
{
return (_endofstorage - _start);
}
6. size()
这个的话就是返回vector的size,原因的话和上面一样。
cpp
size_t size() const
{
return (_finish - _start);
}
7. operator[]
这个的话是运算符重载的[],简单来说就是可以通过下标的方式来对vector里面的内容进行访问。
同时在这里提供了普通版本和const版本。
cpp
T& operator[](size_t pos)
{
assert(pos < size());
return _start[pos];
}
const T& operator[](size_t pos) const
{
assert(pos < size());
return _start[pos];
}
8. print()
这个就是打印,通过迭代器的方式来对vector里面的内容进行打印。
cpp
void print()
{
for (auto e : *this)
{
std::cout << e << ' ';
}
cout << endl;
}
9. 总结
本文围绕C++中的vector容器展开了全面解析,从基础特性到具体接口操作进行了系统梳理。
首先,明确了vector的核心特性及空间结构,让读者对其底层存储有了整体认知;接着,深入讲解了vector类的关键成员与函数,包括私有成员的作用,以及构造函数(默认、拷贝、范围构造)和析构函数在对象创建与销毁时的机制;同时,详细介绍了迭代器相关的begin、end接口,以及erase、pop_back、insert等元素增删操作,reserve、resize、swap等空间与容器管理函数,还有capacity、size的获取方式;此外,还涵盖了重载的方括号运算符(用于便捷访问元素)和print方法(用于元素输出)。
通过这些内容,全面呈现了vector的使用逻辑与核心功能,帮助读者从底层原理到实际操作,完整掌握vector容器的应用。
以下是vector的完整代码:
cpp
#pragma once
#include<iostream>
#include<assert.h>
using namespace std;
namespace struggle
{
template<class T>
class vector
{
public:
typedef T* iterator;
typedef const T* const_iterator;
iterator begin()
{
return _start;
}
iterator end()
{
return _finish;
}
const_iterator begin() const
{
return _start;
}
const_iterator end() const
{
return _finish;
}
vector(size_t n, const T& val = T())
{
resize(n, val);
}
vector(int n, const T& val = T())
{
resize(n, val);
}
template<class InputIterator>
vector(InputIterator first, InputIterator last)
{
while (first != last)
{
push_back(*first);
++first;
}
}
vector(const vector<T>& v)
{
_start = new T[v.capacity()];
for (size_t i = 0; i < v.size(); i++)
{
_start[i] = v._start[i];
}
_finish =_start+v.size();
_endofstorage = _start + v.capacity();
}
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> v)
{
swap(v);
return *this;
}
vector()
:_start(nullptr)
, _finish(nullptr)
, _endofstorage(nullptr)
{}
~vector()
{
delete[] _start;
_start = _finish = _endofstorage = 0;
}
void reserve(size_t n)
{
if (n > capacity())
{
size_t sz = size();
T* tmp = new T[n];
if (_start)
{
//memcpy(tmp, _start, sizeof(T) * sz);
for (int i = 0; i < sz; i++)
{
tmp[i] = _start[i];
}
delete[] _start;
}
_start = tmp;
_finish = _start + sz;
_endofstorage = _start + n;
}
}
void push_back(const T& x)
{
if (_finish == _endofstorage && _endofstorage != 0)
{
reserve(capacity() * 2);
}
else
{
reserve(4);
}
*_finish = x;
++_finish;
}
size_t capacity() const
{
return (_endofstorage - _start);
}
size_t size() const
{
return (_finish - _start);
}
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 resize(size_t n, const T& val=T())
{
if (n < size())
{
_finish = _start + n;
}
else
{
reserve(n);
while (_finish != _start + n)
{
*(_finish) = val;
++_finish;
}
}
}
void erase(iterator pos)
{
assert(pos >= _start && pos < _finish);
iterator it = pos;
while (it + 1 != _finish)
{
*it = *(it + 1);
++it;
}
--_finish;
}
void pop_back()
{
assert(_start != _finish);
--_finish;
}
void insert(iterator pos, const T& x)
{
assert(pos >= _start && pos <= _finish);
size_t len = pos - _start;
if (_finish == _endofstorage && _endofstorage != 0)
{
reserve(capacity() * 2);
}
else
{
reserve(4);
}
pos = _start + len;
iterator end = _finish - 1;
while (end >= pos)
{
*(end + 1) = *end;
--end;
}
*pos = x;
++_finish;
}
/*void print(const vector<int>& v)
{
for(auto e:v)
{
std::cout << e << ' ';
}
cout << endl;
}*/
void print()
{
for (auto e : *this)
{
std::cout << e << ' ';
}
cout << endl;
}
private:
iterator _start;
iterator _finish;
iterator _endofstorage;
};
}