You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

自定义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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.12 09:45:02