目录
一、整体设计
1.1 核心结构
1.2 迭代器实现
二、核心接口实现
2.1 构造函数系列
🌴默认构造
🌴迭代器范围构造
🌴元素填充构造
2.2 拷贝控制
🌵拷贝构造函数
🌵赋值运算符(现代写法)
2.3 析构函数
三、容量管理
3.1 size
3.2 capacity
3.3 reserve 扩容
3.4 resize 调整大小
四、辅助函数
4.1 下标访问
4.2 empty
五、 插入与删除
5.1 insert 插入
5.2 push_back
5.3 pop_back
5.4 erase 删除
六、源码
七、测试示例
一、整体设计
1.1 核心结构
vector
的核心是通过动态内存管理实现一个动态数组。它维护了三个指针:
_start
:指向数组的起始位置。
_finish
:指向数组的当前结束位置(即最后一个元素的下一个位置)。
_endofstorage
:指向分配的内存的结束位置(即最大容量)。
通过这三个指针,vector
可以动态调整数组的大小,同时支持高效的随机访问和插入/删除操作。
template<class T>
class vector
{
private:
T* _start = nullptr; // 数据起始位置
T* _finish = nullptr; // 数据结束位置
T* _endofstorage = nullptr; // 容量结束位置
};
1.2 迭代器实现
通过原生指针实现随机访问迭代器:提供
begin
和end
方法,支持迭代器访问vector
的元素。
typedef T* iterator;
typedef const T* const_iterator;
iterator begin()
{
return _start;
}
iterator end()
{
return _finish;
}
// const版本
const_iterator begin() const
{
return _start;
}
const_iterator end() const
{
return _finish;
}
二、核心接口实现
2.1 构造函数系列
🌴默认构造
默认构造函数初始化一个空的
vector
,所有指针都初始化为nullptr
。
vector() // 使用编译器生成的默认构造
{
}
🌴迭代器范围构造
通过迭代器范围构造一个
vector
,逐个将元素插入到新vector
中。模板参数支持各类迭代器,包括原生指针。
template<class InputIterator>
vector(InputIterator first, InputIterator last)
{
while (first != last)
{
push_back(*first);// 逐个插入元素
++first;
}
}
🌴元素填充构造
构造一个包含
n
个元素的vector
,每个元素初始化为val
。通过reserve
分配足够的内存,并逐个插入元素。
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);
}
}
2.2 拷贝控制
🌵拷贝构造函数
拷贝构造函数通过
reserve
分配与原vector
相同的容量,并逐个复制元素。这样可以确保新vector
的容量和内容与原vector
一致。
vector(const vector<T>& v)
{
reserve(v.capacity());
for (auto e : v) // 范围for遍历
{
push_back(e); // 深拷贝每个元素
}
}
🌵赋值运算符(现代写法)
赋值运算符通过
swap
实现,先将右值的vector
与当前vector
交换,然后返回当前vector
的引用。这种方式称为 "拷贝并交换",可以避免自我赋值的问题。
vector<T>& operator=(vector<T> v) // 传值拷贝临时对象
{
swap(v); // 交换资源
return *this; // 自动释放原内存
}
swap
函数用于交换两个vector
的内容。通过交换指针,可以高效地完成交换操作,而无需复制数据。
void swap(vector<T> v)
{
std::swap(_start, v._start);
std::swap(_finish, v._finish);
std::swap(_endofstorage, v._endofstorage);
}
2.3 析构函数
析构函数释放分配的内存,并将指针置为
nullptr
,避免悬空指针。
~vector()
{
delete[] _start;// 释放数组空间
_start = _finish = _endofstorage = nullptr;// 置空防野指针
}
三、容量管理
3.1 size
返回当前
vector
的大小,即_finish - _start
。
size_t size() const
{
return _finish - _start;
}
3.2 capacity
返回
vector
的当前容量,即_endofstorage - _start
。
size_t capacity() const
{
return _endofstorage - _start;
}
3.3 reserve 扩容
reserve
用于分配至少n
个元素的内存。如果当前容量不足,则分配新的内存,将旧数据复制到新内存中,然后释放旧内存。关键点:必须逐个拷贝元素保证深拷贝,直接内存拷贝(memcpy)会导致浅拷贝问题。
void reserve(size_t n)
{
if (n > capacity())
{
size_t old_size = size(); // 保存原元素个数
T* tmp = new T[n]; // 申请新空间
// 深拷贝旧元素(不能用memcpy)
for (size_t i = 0; i < old_size; ++i)
{
tmp[i] = _start[i]; // 调用T的赋值运算符
}
delete[] _start; // 释放旧空间
// 更新指针
_start = tmp;
_finish = tmp + old_size;
_endofstorage = tmp + n;
}
}
3.4 resize 调整大小
resize
用于调整vector
的大小。如果新大小大于当前大小,则分配更多内存并填充默认值;如果新大小小于当前大小,则直接调整_finish
指针。
void resize(size_t n, const T& val = T())
{
if (n > size()) // 扩容部分
{
reserve(n);
while (_finish < _start + n)
{
*_finish = val; // 填充默认值
++_finish;
}
}
else // 缩容部分
{
_finish = _start + n; // 逻辑缩容,物理容量不变
}
}
四、辅助函数
4.1 下标访问
operator[]
提供随机访问功能,通过索引访问vector
的元素。
T& operator[](size_t pos)
{
assert(pos < size());// 越界检查
return _start[pos];
}
const T& operator[](size_t pos) const
{
assert(pos < size());// 越界检查
return _start[pos];
}
4.2 empty
empty
判断vector
是否为空,即_start
和_finish
是否相等。
void empty()
{
return _start == _finish;
}
五、 插入与删除
5.1 insert 插入
insert
在指定位置插入一个元素。如果内存不足,则通过reserve
扩容。插入时需要将插入点之后的元素向后移动,为新元素腾出空间。迭代器失效处理:扩容后需重新计算pos位置
void insert(iterator pos, const T& val)
{
assert(pos >= _start && pos <= _finish);
// 空间不足时扩容
if (_finish == _endofstorage)
{
size_t len = pos - _start; // 保存相对位置
reserve(capacity() == 0 ? 4 : capacity() * 2);
pos = _start + len; // 解决迭代器失效
}
// 后移元素
iterator it = _finish - 1;
while (it >= pos)
{
*(it + 1) = *it; // 从后向前搬移
--it;
}
*pos = val; // 插入新元素
++_finish; // 更新大小
}
5.2 push_back
push_back
是在vector
的末尾插入一个元素,可以复用insert
实现。
void push_back(const T& val)
{
//if (_finish == _endofstorage)
//{
// reserve(capacity() == 0 ? 4 : capacity() * 2);
//}
//*_finish = val;
//_finish++;
insert(end(), val);// 复用insert逻辑
}
5.3 pop_back
pop_back
删除vector
的最后一个元素,可以复用erase
实现。
void pop_back()
{
//assert(!empty());
//--_finish;
erase(--end());// 复用erase逻辑
}
5.4 erase 删除
erase
删除指定位置的元素。删除时需要将删除点之后的元素向前移动,填补空缺。
void erase(iterator pos)
{
assert(pos >= _start && pos < _finish);
// 前移元素
iterator it = pos + 1;
while (it < _finish)
{
*(it - 1) = *it; // 从前向后搬移
++it;
}
--_finish; // 更新大小
}
六、源码
#pragma once
#include <assert.h>
#include <iostream>
using namespace std;
namespace lv
{
template<class T>
class vector
{
public:
// 定义迭代器类型
typedef T* iterator;
typedef const T* const_iterator;
// 返回迭代器,指向 vector 的起始位置
iterator begin()
{
return _start;
}
// 返回迭代器,指向 vector 的结束位置(即最后一个元素的下一个位置)
iterator end()
{
return _finish;
}
// 常量版本的 begin 和 end,用于 const 对象
const_iterator begin() const
{
return _start;
}
const_iterator end() const
{
return _finish;
}
// 默认构造函数,初始化一个空的 vector
vector()
{
_start = nullptr;
_finish = nullptr;
_endofstorage = nullptr;
}
// 拷贝构造函数,通过 reserve 分配与原 vector 相同的容量,并逐个复制元素
vector(const vector<T>& v)
{
reserve(v.capacity());
for (auto e : v)
{
push_back(e);
}
}
// 交换两个 vector 的内容,通过交换指针实现高效交换
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,逐个插入元素
template<class InputIterator>
vector(InputIterator first, InputIterator last)
{
while (first != last)
{
push_back(*first);
++first;
}
}
// 构造一个包含 n 个元素的 vector,每个元素初始化为 val
vector(size_t n, const T& val = T())
{
reserve(n);
for (size_t i = 0; i < n; i++)
{
push_back(val);
}
}
// 析构函数,释放分配的内存,并将指针置为 nullptr
~vector()
{
delete[] _start;
_start = _finish = _endofstorage = nullptr;
}
// 返回 vector 的当前大小(即元素个数)
size_t size() const
{
return _finish - _start;
}
// 返回 vector 的当前容量(即分配的内存量)
size_t capacity() const
{
return _endofstorage - _start;
}
// 通过索引访问 vector 的元素,带断言检查索引是否越界
T& operator[](size_t pos)
{
assert(pos < size());
return _start[pos];
}
// 常量版本的 operator[],用于 const 对象
const T& operator[](size_t pos) const
{
assert(pos < size());
return _start[pos];
}
// 分配至少 n 个元素的内存,如果当前容量不足,则重新分配内存并复制旧数据
void reserve(size_t n)
{
if (n > capacity())
{
size_t old_size = size();
T* tmp = new T[n];
for (size_t i = 0; i < old_size; ++i)
{
tmp[i] = _start[i];
}
delete[] _start;
_start = tmp;
_finish = tmp + old_size;
_endofstorage = tmp + n;
}
}
// 调整 vector 的大小,如果新大小大于当前大小,则分配更多内存并填充默认值
void resize(size_t n, const T& val = T())
{
if (n > size())
{
reserve(n);
while (_finish < _start + n)
{
*_finish = val;
++_finish;
}
}
else
{
_finish = _start + n;
}
}
// 在指定位置插入一个元素,如果内存不足则扩容
void insert(iterator pos, const T& val)
{
assert(pos >= _start);
assert(pos <= _finish);
if (_finish == _endofstorage)
{
size_t len = pos - _start;
reserve(capacity() == 0 ? 4 : capacity() * 2);
pos = _start + len;
}
iterator it = _finish - 1;
while (it >= pos)
{
*(it + 1) = *it;
--it;
}
*pos = val;
++_finish;
}
// 在 vector 的末尾插入一个元素,通过调用 insert 实现
void push_back(const T& val)
{
insert(end(), val);
}
// 删除 vector 的最后一个元素,通过调用 erase 实现
void pop_back()
{
erase(--end());
}
// 删除指定位置的元素,将删除点之后的元素向前移动
void erase(iterator pos)
{
assert(pos >= _start);
assert(pos < _finish);
iterator it = pos + 1;
while (it < _finish)
{
*(it - 1) = *it;
++it;
}
--_finish;
}
// 判断 vector 是否为空,即 start 和 finish 是否相等
void empty()
{
return _start == _finish;
}
private:
// 指向 vector 起始位置的指针
iterator _start = nullptr;
// 指向 vector 结束位置的指针(即最后一个元素的下一个位置)
iterator _finish = nullptr;
// 指向分配内存结束位置的指针(即最大容量)
iterator _endofstorage = nullptr;
};
// 打印 vector 的内容
void print_vector(const vector<int>& v)
{
auto it = v.begin();
while (it < v.end())
{
cout << *it << " ";
it++;
}
cout << endl;
}
// 测试 vector 的功能
void test_vector1()
{
//......
}
}
七、测试示例
#include <iostream>
#include <cassert>
using namespace std;
void test_vector()
{
// 测试默认构造函数和基本的 push_back 操作
{
vector<int> v;
assert(v.empty());
assert(v.size() == 0);
assert(v.capacity() == 0);
v.push_back(1);
v.push_back(2);
v.push_back(3);
assert(v.size() == 3);
assert(v.capacity() >= 3);
assert(v[0] == 1);
assert(v[1] == 2);
assert(v[2] == 3);
}
// 测试拷贝构造函数
{
vector<int> v1;
v1.push_back(10);
v1.push_back(20);
v1.push_back(30);
vector<int> v2(v1);
assert(v2.size() == 3);
assert(v2[0] == 10);
assert(v2[1] == 20);
assert(v2[2] == 30);
}
// 测试赋值运算符
{
vector<int> v1;
v1.push_back(100);
v1.push_back(200);
vector<int> v2;
v2 = v1;
assert(v2.size() == 2);
assert(v2[0] == 100);
assert(v2[1] == 200);
}
// 测试迭代器构造函数
{
vector<int> v1;
v1.push_back(1);
v1.push_back(2);
v1.push_back(3);
vector<int> v2(v1.begin(), v1.end());
assert(v2.size() == 3);
assert(v2[0] == 1);
assert(v2[1] == 2);
assert(v2[2] == 3);
}
// 测试插入操作
{
vector<int> v;
v.push_back(1);
v.push_back(2);
v.push_back(3);
v.insert(v.begin() + 1, 10);
assert(v.size() == 4);
assert(v[0] == 1);
assert(v[1] == 10);
assert(v[2] == 2);
assert(v[3] == 3);
v.insert(v.begin(), 20);
assert(v.size() == 5);
assert(v[0] == 20);
assert(v[1] == 1);
assert(v[2] == 10);
assert(v[3] == 2);
assert(v[4] == 3);
}
// 测试删除操作
{
vector<int> v;
v.push_back(1);
v.push_back(2);
v.push_back(3);
v.push_back(4);
v.erase(v.begin() + 1);
assert(v.size() == 3);
assert(v[0] == 1);
assert(v[1] == 3);
assert(v[2] == 4);
v.pop_back();
assert(v.size() == 2);
assert(v[0] == 1);
assert(v[1] == 3);
}
// 测试 resize 和 reserve
{
vector<int> v;
v.push_back(1);
v.push_back(2);
v.resize(5);
assert(v.size() == 5);
assert(v[0] == 1);
assert(v[1] == 2);
assert(v[2] == 0); // 默认值
assert(v[3] == 0);
assert(v[4] == 0);
v.resize(3);
assert(v.size() == 3);
assert(v[0] == 1);
assert(v[1] == 2);
assert(v[2] == 0);
v.reserve(10);
assert(v.capacity() >= 10);
}
// 测试边界条件
{
vector<int> v;
assert(v.empty());
assert(v.size() == 0);
try
{
v[0]; // 应该抛出断言错误
assert(false);
}
catch (...)
{
assert(true);
}
v.push_back(1);
v.erase(v.begin());
assert(v.empty());
}
cout << "All tests passed!" << endl;
}