STL容器终极解剖:C++ vector源码级实现指南 | 从内存分配到异常安全的全流程避坑
🤖💻👨💻👩💻🌟🚀 🤖🌟 欢迎降临张有志的未来科技实验室 🤖🌟 专栏: C++ 👨💻👩💻 先赞后看,已成习惯👨💻👩💻 👨💻👩💻 创作不易,多多支持👨💻👩💻 🚀 启动创新引擎,揭秘C语言的密码🚀 ![]()
文章目录
- C++ Vector模拟实现全景
- 核心接口
- 🧠 核心实现原理
- 关键组件实现:
- 👨💻 vector接口实战演练
- 性能优化关键
C++ Vector模拟实现全景
核心接口
-
三段式指针管理:
_start
→ 存储空间起始_finish
→ 有效数据末尾_end_of_storage
→ 内存空间末尾
-
扩容策略:
-
深拷贝处理:
// 拷贝构造函数示例 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)
💡贴士: 迭代器本质是原生指针的封装,需实现operator++
和operator*
关键组件实现:
// 三段式指针定义
template <class T>
class vector {
public:
using iterator = T*;
using const_iterator = const T*T* _start; // 内存起始T* _finish; // 有效数据末尾T* _end_of_storage; // 内存空间末尾
};
构造函数: 用于创建 vector 对象,包括默认构造、拷贝构造以及根据指定元素个数和范围构造等。
//部分构造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 对象占用的资源。
~vector() {if (_start) {clear();}_start = _finish = _end_of_storage = nullptr;}
需要注意:不能直接使用delete[],会导致程序崩溃(vector<vector< T >>),需要挨个调用~T()
容量管理接口:
reserve
:预留指定容量的存储空间。
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 的容量。
//容器总容量
size_t capacity() {return _end_of_storage - _start;
}
size
:返回当前 vector 中元素的数量。
size_t size()const {return _finish - _start;
}
rest_size
:返回当前 vector 剩余的可存储元素的空间大小。
size_t rest_size() {return capacity() - size();
}
迭代器接口:
- begin 和 end:返回指向 vector 首元素和尾后元素的迭代器。
//首元素iterator begin() {return _start;}//有效尾元素iterator end() {return _finish;}const_iterator begin() const {return _start;}const_iterator end() const {return _finish;}
元素操作接口:
push_back
:在 vector 尾部插入一个元素。
void push_back(const T& v) {if (_finish == _end_of_storage) {reserve(capacity() == 0 ? 4 : 2 * size());}*_finish = v;++_finish;
}
insert
:在指定位置插入一个元素。
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
:删除指定位置的元素。
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 中的所有元素。
void clear() {for (auto it = _start; it != _end_of_storage; ++it) {it->~T();}_start = _finish;
}
查找和调整大小接口:
find
:查找指定元素在 vector 中的位置。
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 的大小。
void resize(size_t n) {if (n < size()) {_finish = _start + n;}else{reserve(n);}
}
运算符重载接口:
operator[]
:通过下标访问 vector 中的元素。
T& operator[](size_t n) {assert(_start && n>=0);return _start[n];
}
operator<<
和operator>>
:重载输入输出运算符,方便对 vector 进行输入输出操作。
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;
}
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接口实战演练
- 🎯测试函数
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()); // 验证深拷贝
}
- 🧪 插入删除测试
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倍扩容验证
}
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%扩容开销</知识卡片>
常见问题避坑
⚠️ 迭代器失效问题
- 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;
⚠️ 深浅拷贝陷阱
// 错误示例:直接复制指针
vector(const vector& v) {_start = v._start; // 导致双杀问题
}
// 正确实现:深拷贝
vector(const vector& v) {reserve(v.size());std::copy(v.begin(), v.end(), _start);
}