为容器 class 重载 `[]` 运算符时,`&` 的重要性是什么?

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

假设我有这个简单的容器class

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];
}

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

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];
}

编译器抛出错误

lvalue required as left of operand assignment

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

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

具体来说,当你写 arr[0] 时,如果你的重载中没有引用,那只会 return 一个整数(无论 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 是什么意思?通过引用重载,您正在 return 对数组的第一个元素(左值)进行引用(内存位置)。阅读 this 可能会帮助您更好地理解它。

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

如果没有 &,您的 operator[] 将 return copy(即值)int相反。

当函数 return 是一个值而不是引用时,编译器会创建一个临时变量来保存该值。该临时文件只存在于创建它的语句结束之前。该临时变量称为 rvalue,即在赋值的 right-hand 端使用的值。要更长时间地保留该值,调用者必须将其分配给另一个变量。

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