🤖💻👨💻👩💻🌟🚀 🤖🌟 欢迎降临张有志的未来科技实验室 🤖🌟 专栏: C++ 👨💻👩💻 先赞后看,已成习惯👨💻👩💻 👨💻👩💻 创作不易,多多支持👨💻👩💻 🚀 启动创新引擎,揭秘C语言的密码🚀
文章目录
- [C++ Vector模拟实现全景](#C++ Vector模拟实现全景)
- 核心接口
- [🧠 核心实现原理](#🧠 核心实现原理)
- 关键组件实现:
-
- [👨💻 vector接口实战演练](#👨💻 vector接口实战演练)
- 性能优化关键
C++ Vector模拟实现全景
用户代码 push_back vector operator new memcpy operator delete 添加元素 检查容量 直接插入 申请新内存 返回指针 数据迁移 迁移完成 释放旧内存 alt [容量足够] [需要扩容] 用户代码 push_back vector operator new memcpy operator delete
核心接口
内存管理 _start指针 _finish指针 _end_of_storage指针 核心接口 push_back insert erase 迭代器体系 正向迭代器 const迭代器
🔧 STL vector是C++中最核心的顺序容器,其实现涉及以下关键技术点:
-
三段式指针管理:
_start
→ 存储空间起始_finish
→ 有效数据末尾_end_of_storage
→ 内存空间末尾
-
扩容策略:
首次push_back 倍增策略 空容器 预分配4元素空间 容量不足 新容量=旧容量*2
-
深拷贝处理:
cpp// 拷贝构造函数示例 vector(const vector<T>& v) { reserve(v.size()); for (auto& e : v) push_back(e); }
🧠 核心实现原理
容量增长公式:
n e w _ c a p a c i t y = m a x ( o l d _ c a p a c i t y × 2 , d e m a n d ) new\_capacity = max(old\_capacity × 2, \ demand) new_capacity=max(old_capacity×2, demand)
push_back() reserve() operator new() std::copy() _finish 准备插入新元素 发起容量检查请求 检查当前容器容量 请求分配新内存 返回新内存指针 发起数据迁移请求 数据迁移完成通知 无需扩容,直接插入 alt [容量不足] [容量充足] 插入新元素 新元素插入完成 push_back() reserve() operator new() std::copy() _finish
💡贴士 : 迭代器本质是原生指针的封装,需实现operator++
和operator*
关键组件实现:
cpp
// 三段式指针定义
template <class T>
class vector {
public:
using iterator = T*;
using const_iterator = const T*
T* _start; // 内存起始
T* _finish; // 有效数据末尾
T* _end_of_storage; // 内存空间末尾
};
构造函数: 用于创建 vector 对象,包括默认构造、拷贝构造以及根据指定元素个数和范围构造等。
cpp
//部分构造
vector(iterator start=nullptr, iterator finish = nullptr, iterator end_of_storage = nullptr)
:_start(start)\
,_finish(finish)\
,_end_of_storage(end_of_storage)
{}
//拷贝构造
vector(const vector<T>& v) {
reserve(v.size());
for (auto& e : v)
push_back(e);
}
//构造
template<class T> vector(size_t n, const T& val=T())
:_start(nullptr)
,_finish(nullptr)
,_end_of_storage(nullptr)
{
reserve(n);
while (n--) {push_back(val);}
}
//部分
template<class T> vector(T first, T last) {
while (first != last) {
push_back(*first);
++first;
}
}
析构函数:负责释放 vector 对象占用的资源。
cpp
~vector() {
if (_start) {
clear();
}
_start = _finish = _end_of_storage = nullptr;
}
需要注意:不能直接使用delete[],会导致程序崩溃(vector<vector< T >>),需要挨个调用~T()
容量管理接口:
reserve
:预留指定容量的存储空间。
cpp
void reserve(size_t n) {
//防止给定数字比容量小
if(n>capacity()){
size_t old_size = size();
T* tmp = new T[n];
std::copy(_start, _finish, tmp);
delete[] _start;
_start = tmp;
_finish = tmp + old_size;
_end_of_storage = _start + n;
}
else {
return;
}
}
capacity
:返回当前 vector 的容量。
cpp
//容器总容量
size_t capacity() {
return _end_of_storage - _start;
}
size
:返回当前 vector 中元素的数量。
cpp
size_t size()const {
return _finish - _start;
}
rest_size
:返回当前 vector 剩余的可存储元素的空间大小。
cpp
size_t rest_size() {
return capacity() - size();
}
迭代器接口:
- begin 和 end:返回指向 vector 首元素和尾后元素的迭代器。
cpp
//首元素
iterator begin() {
return _start;
}
//有效尾元素
iterator end() {
return _finish;
}
const_iterator begin() const {
return _start;
}
const_iterator end() const {
return _finish;
}
元素操作接口:
push_back
:在 vector 尾部插入一个元素。
cpp
void push_back(const T& v) {
if (_finish == _end_of_storage) {
reserve(capacity() == 0 ? 4 : 2 * size());
}
*_finish = v;
++_finish;
}
insert
:在指定位置插入一个元素。
cpp
T& insert(size_t pos, const T& v) {
if (_finish == _end_of_storage)
reserve(capacity() == 0 ? 4 : 2 * size());
for (size_t i = size(); i > pos; --i)
*(_start + i) = *(_start + i - 1);
_start[pos] = v;
++_finish;
return *_finish;
}
erase
:删除指定位置的元素。
cpp
iterator erase(size_t pos) {
if (pos<begin() || pos>end()) {
throw std::out_of_range("无效位置");
}
size_t offset = pos - begin();
auto m_pos = _start + offset;
m_pos->~T();
if (m_pos + 1 != _finish) {
std::move(m_pos + 1, _finish, m_pos);
}
return m_pos;
}
clear
:清空 vector 中的所有元素。
cpp
void clear() {
for (auto it = _start; it != _end_of_storage; ++it) {
it->~T();
}
_start = _finish;
}
查找和调整大小接口:
find
:查找指定元素在 vector 中的位置。
cpp
template<class T> int find(const my::vector<T>& dst) {
iterator bg = begin();
iterator ed = end();
int pos = 0;
while (bg < ed) {
if (*bg == dst)
return pos;
else {
++pos;
++bg;
}
}
return -1;
}
resize
:调整 vector 的大小。
cpp
void resize(size_t n) {
if (n < size()) {
_finish = _start + n;
}
else{
reserve(n);
}
}
运算符重载接口:
operator[]
:通过下标访问 vector 中的元素。
cpp
T& operator[](size_t n) {
assert(_start && n>=0);
return _start[n];
}
operator<<
和operator>>
:重载输入输出运算符,方便对 vector 进行输入输出操作。
cpp
std::ostream& operator<<(std::ostream& os, const my::vector<T>& v) {
for (auto it = v.begin(); it != v.end(); ++it) {
if (it != v.begin()) os << " "; // 保证空格分隔
if constexpr (has_output_operator<T>::value) {
os << *it;
}
else {
os << typeid(T).name() << "@" << &*it;
}
}
return os;
}
cpp
friend std::istream& operator >> (std::istream& is, vector<T>& v) {
T x = 0;
while (is >> x) {
if (v._finish == v._end_of_storage)
v.reserve(2 * v.capacity());
v.push_back(x);
}
return is;
}
👨💻 vector接口实战演练
- 🎯测试函数
cpp
void test_constructors() {
// 初始化列表构造测试
my::vector<int> v1{ 7, 28, 1987 };
assert(v1.size() == 3 && v1[0] == 7 && v1[2] == 1987);
// 拷贝构造函数测试
my::vector<int> v2 = v1;
assert(v2.size() == 3 && v2.capacity() == 3);
v2.push_back(2023);
assert(v1.size() != v2.size()); // 验证深拷贝
}
- 🧪 插入删除测试
cpp
void test_capacity_management() {
my::vector<std::string> v;
// 🧪 容量增长测试
assert(v.capacity() == 0);
v.push_back("Hello");
assert(v.capacity() == 4); // ✅ 初始扩容策略验证
for (int i = 0; i < 10; ++i) v.push_back("World");
assert(v.capacity() == 16); // ✅ 2倍扩容验证
}
cpp
void test_element_operations() {
my::vector<int> v{ 5,3,1 };
// ✅ 正常插入操作测试
v.insert(1, 999); // [5,999,3,1]
assert(v.size() == 4 && v[1] == 999);
// ✅ 迭代器删除测试
auto it = v.erase(v.begin() + 2); // 删除索引2(值3)
assert(*it == 1 && v.size() == 3);
// ✅ 迭代器失效测试
my::vector<int> v2{ 1,2,3 };
auto old_cap = v2.capacity();
auto beg = v2.begin();
v2.insert(1, 5); // 触发扩容
assert(old_cap < v2.capacity() && "Capacity should increase");
try {
*beg = 10; // ⚠️ 旧迭代器应失效
assert(false);
}
catch (...) {} // 实际可能崩溃而非抛异常
}
性能优化关键
操作 | 时间(1k次) | 内存波动 |
---|---|---|
push_back | 12ms | 阶梯式增长 |
insert(0) | 356ms | 频繁扩容 |
erase末尾 | 3ms | 无变化 |
知识卡片📌 reserve预分配可减少87%扩容开销</知识卡片>
常见问题避坑
⚠️ 迭代器失效问题
diff
- vector<int> v{1,2,3};
- auto it = v.begin();
- v.push_back(4); // 可能导致迭代器失效
+ size_t idx = it - v.begin(); // 改用偏移量
+ v.push_back(4);
+ it = v.begin() + idx;
⚠️ 深浅拷贝陷阱
cpp
// 错误示例:直接复制指针
vector(const vector& v) {
_start = v._start; // 导致双杀问题
}
// 正确实现:深拷贝
vector(const vector& v) {
reserve(v.size());
std::copy(v.begin(), v.end(), _start);
}