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; }
关键实现要点
下标运算符的两种重载
- 非
const版本返回int&:直接返回链表节点中data的引用,让a[0]成为可修改的左值,支持赋值操作。 const版本返回const int&:确保const DynamicArray对象只能通过下标读取元素,不能修改。
- 非
赋值运算符的深拷贝
- 先清空当前对象的链表内存,避免内存泄漏。
- 逐节点拷贝源对象的链表数据,防止浅拷贝导致的双重释放问题。
- 加入自赋值判断,避免不必要的内存操作。
边界检查
- 在
getNode函数中判断下标是否越界,抛出std::out_of_range异常,避免非法内存访问。
- 在
内容的提问来源于stack exchange,提问作者the learner
相关产品推荐
相关产品推荐

