重载容器类的"[]"运算符时,"&"的重要性是什么?

What is the importance of `&` when overloading the `[]` operator for a container class?

本文关键字:重要性 是什么 运算符 容器类 重载      更新时间:2024-05-23

假设我有一个简单的容器类

class Array{
private:
int m_l{};
int *m_d{};

public:
Array() = default;
Array(int len)
: m_l{len}
{
assert(len >= 0);
if (len > 0)
{
m_d = new int[len]{};
}
}
~Array(){
delete[] m_d;
}
// -------------------------------------------
int& operator[](int i){
assert(i >= 0 && i <= m_l && "Index in operator [] out of range");
return m_d[i];
}
//--------------------------------------------
};

特别是

int& operator[](int i)
{
assert(i >= 0 && i <= m_l && "Index in operator [] out of range");
return m_d[i];
}

我已经重载了[]运算符来获得下标,我只是在学习运算符重载和容器类。

Array arr{5};
arr[0] = 32;
arr[1] = 34;
std::cout << arr[0];

32

代码按预期编译和执行,但如果我从函数中删除&,使其成为

int operator[](int i)
{
assert(i >= 0 && i <= m_l && "Index in operator [] out of range");
return m_d[i];
}

编译器抛出错误

操作数分配左侧所需的左值

为什么会出现此错误,&在函数中的意义是什么?

如果没有下标运算符重载中的引用,您将从函数返回一个临时右值。右值不能出现在赋值操作的左侧。

具体来说,当您编写arr[0]时,如果重载中没有引用,它只会返回一个整数(无论arr[0]的值是多少(。

Array arr{5};
arr[0]; //Without the reference, this returns 5.
5 = 32; //Written out, this is what the expression turns to.

5是一个不能赋值的右值——5 = 32是什么意思?使用引用重载,您将返回对数组的第一个元素的引用(内存位置(,该元素是左值。阅读这篇文章可能会帮助你更好地理解它。

int&中的&表示operator[]int变量返回引用(即别名,通常实现为内存地址(。一旦绑定到一个变量,任何分配给引用的值都会被分配给它所引用的变量

如果没有&operator[]将返回int副本(即值(。

当函数返回值而不是引用时,编译器会创建一个临时变量来保存该值。这个临时变量只存在到创建它的语句末尾。这个临时变量被称为右值,即在赋值的右侧使用的值。若要将该值保留更长时间,调用者必须将其分配给另一个变量。

诸如命名变量、对变量的引用等都是lvalue,即它们可以在赋值的左侧使用。右值不能在左侧使用,只能在右侧使用。