自定义vector实现打印时触发未处理异常,求排查原因
问题分析与修复
直接触发打印异常的原因
你的main函数里的打印循环逻辑完全错误:
for (auto i = b.begin(); i != b.end(); i++) { cout << b[*i] << endl; }
这里的i是指向数组元素的指针,*i取到的是元素的值(你push的都是42),然后用b[42]去访问容器,而此时你的容器实际只存了30个元素,42 >= _capacity,直接触发越界抛出的异常。正确的写法应该是直接打印*i,或者用索引遍历:
// 写法1:直接解引用迭代器 for (auto i = b.begin(); i != b.end(); i++) { cout << *i << endl; } // 写法2:索引遍历 for (uint64_t i = 0; i < b.get_cp(); i++) { cout << b[i] << endl; }
核心逻辑错误(内存与容量管理混乱)
你的badvector最大的问题是完全误解了capacity的定义,以及初始化逻辑错误:
1. capacity_count函数逻辑彻底错误
标准vector中,capacity是当前分配的内存能容纳的最大元素数,size是已存储的元素数。而你的capacity_count却遍历整个数组,把非0元素的数量当成_capacity,这会导致:
- 当存储0值元素时,
_capacity不会正确增加,push_back逻辑完全混乱 - 新分配的数组未初始化区域的垃圾值会被统计成非0,导致
_capacity被错误赋值
修复方式:删掉capacity_count函数,直接维护_capacity作为已存储元素的数量,_size作为当前内存能容纳的最大元素数(即标准意义的capacity)。
2. 初始化函数参数错误
第二个initialize函数接收的参数是sz,但循环用的是_size,导致新分配的内存区域没有被完全初始化:
void initialize(uint64_t sz, shared_ptr<T[]> &ptrarr) { // 错误:用了_size而不是sz for (int i = 0; i < _size; i++) { ptrarr[i] = 0; } }
改成用sz遍历,才能把新分配的整个数组初始化。
3. 初始化方式的误解
你猜测用nullptr初始化数组是不必要的,对于int类型,用0初始化没问题,但核心问题是初始化范围错误,以及容量管理逻辑错误。
修正后的完整代码
#include <iostream> #include <memory> #include <algorithm> using namespace std; template <typename T> class badvector { private: uint64_t _size; // 对应标准vector的capacity:当前内存可容纳的最大元素数 uint64_t _capacity; // 对应标准vector的size:已存储的元素数 shared_ptr<T[]> arrptr; bool resizable; void initialize() { for (uint64_t i = 0; i < _size; i++) { arrptr[i] = 0; } } void initialize(uint64_t sz, shared_ptr<T[]> &ptrarr) { for (uint64_t i = 0; i < sz; i++) { ptrarr[i] = 0; } } public: explicit badvector() : _size(5), _capacity(0), arrptr(new T[5]), resizable(true) { initialize(); } ~badvector() = default; uint64_t get_cp() { return this->_capacity; } uint64_t capacity() { return this->_size; } void push_back(T arg) { if (_capacity == _size) { resize(_size + 5); } arrptr[_capacity] = arg; ++this->_capacity; } void reserve(uint64_t sz) { if (sz <= _size) return; // 只扩容不缩容 if (!resizable) { throw "Error, you are not able to reserve any more place, you used resize"; } shared_ptr<T[]> temp(new T[sz]); initialize(sz, temp); for (uint64_t i = 0; i < _capacity; i++) { temp[i] = arrptr[i]; } arrptr = temp; _size = sz; } void resize(uint64_t sz) { reserve(sz); resizable = false; } T& operator[](uint64_t position) { // 返回引用,支持修改 if (position >= _capacity || position < 0) { throw "badvector out of range"; }; return arrptr[position]; } const T& operator[](uint64_t position) const { // const版本 if (position >= _capacity || position < 0) { throw "badvector out of range"; }; return arrptr[position]; } void print(uint64_t num) { if (num >= _capacity || num < 0) { throw "badvector out of range"; } cout << arrptr[num] << endl; } const T* cbegin() const { return arrptr.get(); } T* begin(){ return arrptr.get(); } const T* cend() const { return arrptr.get() + _capacity; // 指向已存储元素的末尾,不是内存末尾 } T* end() { return arrptr.get() + _capacity; } }; int main() { badvector<int> b; b.reserve(30); cout << "capacity " << b.capacity() << endl << "size " << b.get_cp() << endl; for (int i = 0; i < 30; i++) { b.push_back(42); } cout << "capacity after push_back: " << b.capacity() << endl << "size after push_back: " << b.get_cp() << endl; // 正确的打印方式 for (auto i = b.begin(); i != b.end(); i++) { cout << *i << endl; } }
关键修正点总结
- 修正了
_size和_capacity的定义,符合标准容器的语义 - 删除了错误的
capacity_count函数,直接维护_capacity - 修复了初始化函数的循环范围错误
- 修正了
begin()/end()的返回值,指向已存储元素的范围 - 修复了main函数中的打印逻辑
内容的提问来源于stack exchange,提问作者user21148656
相关产品推荐
相关产品推荐

