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

自定义MyArrayList类operator[]重载函数调用异常问题求助

问题:自定义数组类MyArrayList的operator[]重载无法正确调用

我正在实现一个带边界检查的自定义数组类MyArrayList,重载了两个operator[]运算符:

  • const版本:用于获取元素值,支持num1 = list1[2]这类取值操作;
  • 非const版本:用于为元素赋值,支持list1[2] = 5这类赋值操作。

但运行main函数时,发现无法正确调用对应的重载函数——比如取值操作没有调用到const版本的operator[]。尝试过用friend关键字改写第二个重载函数,但觉得这不是合适方案,现在找不到解决办法,完整代码如下:

#include <iostream>

template <typename Data>
class MyArrayList {
    private :
        Data* data_storage; 
        int num_of_elements;
        int array_size;
        int idx_cursor;
    public :
        MyArrayList(int _size);
        void add_element(Data new_data);
        void remove_element();
        Data operator[](int idx) const;
        MyArrayList& operator[](int idx);
        void operator=(Data new_data);
        ~MyArrayList();
};

template <typename Data>
MyArrayList<Data>::MyArrayList(int _size) {
    array_size = _size;
    data_storage = new Data[array_size];
    num_of_elements = 0;
    idx_cursor = 0;
}

template <typename Data>
void MyArrayList<Data>::add_element(Data new_data) {
    if(num_of_elements > array_size) {
        std::cout << "Unable to store more." << std::endl;
        return; 
    }
    data_storage[++num_of_elements - 1] = new_data;
}

template <typename Data>
void MyArrayList<Data>::remove_element() {
    if(num_of_elements <= 0) {
        std::cout << "Unable to delete anymore" << std::endl; 
        return;
    }
    
    Data* temp = data_storage;
    delete[] data_storage;
    
    data_storage = new Data[--num_of_elements];  
    for(int i = 0; i < num_of_elements; i++)
        data_storage[i] = temp[i];
    
    delete[] temp; 
}

template <typename Data>
MyArrayList<Data>::~MyArrayList() {
    delete[] data_storage;
}

template <typename Data>
Data MyArrayList<Data>::operator[](int idx) const { //var = list1[5];
    if(idx < 0) {
        int new_idx = idx;
        while(new_idx < 0) {
        std::cout << "IndexOutofBounds! Enter new index." << std::endl;
        std::cin >> new_idx; std::cout << std::endl;
        new_idx--;
        }
        idx = new_idx;
    }
    
    return data_storage[idx];
}

template <typename Data>
 MyArrayList<Data>& MyArrayList<Data>::operator[](int idx){ // list1[2] = 5;
    idx_cursor = idx;
    return *this;

}

template <typename Data>
void MyArrayList<Data>::operator=(Data new_data){
    data_storage[idx_cursor] = new_data;        
} 

int main() {
    int num1;
    MyArrayList<int> list1(5);
    
    list1.add_element(6);
    list1.add_element(7);
    list1.add_element(8);
    list1.add_element(9);
    list1[2] = 5; //possible
    //std::cout << num1 << std::endl; //not possible. probably not calling the first overloaded operator[]()? 
    
}

问题分析与解决方案

核心问题

你的实现逻辑偏离了operator[]的常规设计:

  1. 非const版operator[]返回MyArrayList&,再通过额外重载的operator=完成赋值,这不符合C++中operator[]的预期行为——标准容器的operator[]直接返回元素引用,同时支持取值和赋值。
  2. 这种设计导致非const对象的取值操作(比如num1 = list1[2])会优先调用非const版operator[],但该版本返回的是对象引用,无法直接转换为Data类型,进而引发异常。

修正方案

直接调整两个operator[]的返回值,让非const版返回元素引用,同时统一边界检查逻辑:

  1. 修改operator[]返回类型:
    • const版保持返回Data(或const Data&以避免拷贝,提升效率);
    • 非const版返回Data&,直接指向数组元素,天然支持赋值和取值。
  2. 抽离边界检查逻辑:将重复的边界检查写成私有成员函数,避免代码冗余。
  3. 修复其他潜在问题:比如add_element中的判断条件错误(应为num_of_elements >= array_size),简化remove_element的实现逻辑。

修改后的完整代码

#include <iostream>

template <typename Data>
class MyArrayList {
private:
    Data* data_storage;
    int num_of_elements;
    int array_size;

    // 统一边界检查,返回合法索引
    int validate_index(int idx) const {
        if (idx < 0 || idx >= num_of_elements) {
            int new_idx = idx;
            while (new_idx < 0 || new_idx >= num_of_elements) {
                std::cout << "IndexOutofBounds! Enter new index (0~" << num_of_elements-1 << "): " << std::endl;
                std::cin >> new_idx;
            }
            idx = new_idx;
        }
        return idx;
    }

public:
    MyArrayList(int _size);
    void add_element(Data new_data);
    void remove_element();
    Data operator[](int idx) const; // 取值:num1 = list1[2]
    Data& operator[](int idx);      // 赋值/取值:list1[2] = 5 或 num1 = list1[2]
    ~MyArrayList();
};

template <typename Data>
MyArrayList<Data>::MyArrayList(int _size) {
    array_size = _size;
    data_storage = new Data[array_size](); // 初始化元素为默认值
    num_of_elements = 0;
}

template <typename Data>
void MyArrayList<Data>::add_element(Data new_data) {
    if (num_of_elements >= array_size) { // 修正判断条件
        std::cout << "Unable to store more." << std::endl;
        return;
    }
    data_storage[num_of_elements++] = new_data; // 简化写法
}

template <typename Data>
void MyArrayList<Data>::remove_element() {
    if (num_of_elements <= 0) {
        std::cout << "Unable to delete anymore" << std::endl;
        return;
    }
    num_of_elements--; // 无需重新分配数组,直接减少元素计数即可
}

template <typename Data>
MyArrayList<Data>::~MyArrayList() {
    delete[] data_storage;
}

template <typename Data>
Data MyArrayList<Data>::operator[](int idx) const {
    idx = validate_index(idx);
    return data_storage[idx];
}

template <typename Data>
Data& MyArrayList<Data>::operator[](int idx) {
    idx = validate_index(idx);
    return data_storage[idx];
}

int main() {
    int num1;
    MyArrayList<int> list1(5);

    list1.add_element(6);
    list1.add_element(7);
    list1.add_element(8);
    list1.add_element(9);

    list1[2] = 5; // 调用非const版operator[]完成赋值
    num1 = list1[2]; // 调用非const版operator[]完成取值
    std::cout << num1 << std::endl; // 输出5

    // 测试const对象调用const版operator[]
    const MyArrayList<int> const_list = list1;
    num1 = const_list[1]; // 调用const版operator[]
    std::cout << num1 << std::endl; // 输出7
}

关键说明

  • 非const对象的取值/赋值操作会优先调用非const版operator[],符合C++重载决议规则;
  • const对象只能调用const版operator[],保证了const对象的只读性;
  • 抽离的validate_index函数统一处理边界检查,避免代码冗余;
  • 简化后的add_element和remove_element修复了原代码中的逻辑错误,提升了效率。

内容的提问来源于stack exchange,提问作者ragedhumancompiler

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.26 07:28:08