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

C++重载[]与=运算符实现动态数组赋值时出现左值错误

问题分析与解决方案

出现"expression must be a modifiable lvalue"错误的核心原因:你重载的operator[]返回的是**值类型(如int)**或const引用,导致a[0]是不可修改的临时对象/只读引用,无法作为赋值操作的左值。要实现像普通数组那样的赋值,必须让operator[]返回可修改的引用。

以下是完整的单链表版DynamicArray实现,包含下标运算符、赋值运算符的正确重载:


1. 头文件 dynamicarray.h

#include <stdexcept>

struct Node {
    int data;
    Node* next;
    Node(int val) : data(val), next(nullptr) {}
};

class DynamicArray {
private:
    Node* head;
    int size;

    // 辅助函数:定位指定下标的节点(带越界检查)
    Node* getNode(int index) const {
        if (index < 0 || index >= size) {
            throw std::out_of_range("DynamicArray: Index out of bounds");
        }
        Node* current = head;
        for (int i = 0; i < index; ++i) {
            current = current->next;
        }
        return current;
    }

    // 辅助函数:清空当前链表
    void clear() {
        Node* current = head;
        while (current != nullptr) {
            Node* temp = current;
            current = current->next;
            delete temp;
        }
        head = nullptr;
        size = 0;
    }

public:
    // 默认构造
    DynamicArray() : head(nullptr), size(0) {}

    // 析构
    ~DynamicArray() {
        clear();
    }

    // 拷贝构造(深拷贝)
    DynamicArray(const DynamicArray& other) : head(nullptr), size(0) {
        Node* otherCurr = other.head;
        Node** newHead = &head;
        while (otherCurr != nullptr) {
            *newHead = new Node(otherCurr->data);
            otherCurr = otherCurr->next;
            newHead = &((*newHead)->next);
            size++;
        }
    }

    // 赋值运算符重载(深拷贝,防止自赋值)
    DynamicArray& operator=(const DynamicArray& other) {
        if (this == &other) {
            return *this;
        }
        clear();
        Node* otherCurr = other.head;
        Node** newHead = &head;
        while (otherCurr != nullptr) {
            *newHead = new Node(otherCurr->data);
            otherCurr = otherCurr->next;
            newHead = &((*newHead)->next);
            size++;
        }
        return *this;
    }

    // 非const版下标运算符:返回可修改引用,支持读写
    int& operator[](int index) {
        Node* node = getNode(index);
        return node->data;
    }

    // const版下标运算符:返回只读引用,用于const对象
    const int& operator[](int index) const {
        Node* node = getNode(index);
        return node->data;
    }

    // 辅助功能:尾插元素
    void push_back(int val) {
        if (head == nullptr) {
            head = new Node(val);
        } else {
            Node* current = head;
            while (current->next != nullptr) {
                current = current->next;
            }
            current->next = new Node(val);
        }
        size++;
    }

    // 获取当前元素个数
    int getSize() const {
        return size;
    }
};

2. 测试文件 dynamicarrayTester.cpp

#include "dynamicarray.h"
#include <iostream>

int main() {
    DynamicArray a;
    a.push_back(10);
    a.push_back(20);
    a.push_back(30);

    // 读取元素
    std::cout << "a[0]初始值:" << a[0] << std::endl;
    // 修改元素(关键测试:此时不会再报lvalue错误)
    a[0] = 27;
    std::cout << "修改后a[0]:" << a[0] << std::endl;

    // 赋值运算符测试(深拷贝验证)
    DynamicArray b;
    b = a;
    std::cout << "b[0]初始值:" << b[0] << std::endl;
    b[1] = 50;
    std::cout << "修改b[1]后,a[1]的值:" << a[1] << std::endl;

    // const对象测试
    const DynamicArray c = a;
    std::cout << "const对象c[0]的值:" << c[0] << std::endl;

    return 0;
}

关键实现要点

  1. 下标运算符的两种重载

    • 非const版本返回int&:直接返回链表节点中data的引用,让a[0]成为可修改的左值,支持赋值操作。
    • const版本返回const int&:确保const DynamicArray对象只能通过下标读取元素,不能修改。
  2. 赋值运算符的深拷贝

    • 先清空当前对象的链表内存,避免内存泄漏。
    • 逐节点拷贝源对象的链表数据,防止浅拷贝导致的双重释放问题。
    • 加入自赋值判断,避免不必要的内存操作。
  3. 边界检查

    • 在getNode函数中判断下标是否越界,抛出std::out_of_range异常,避免非法内存访问。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.24 20:02:43