0

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

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

编译器抛出错误

左值需要作为操作数赋值的左侧

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

4

2 回答 2

3

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

具体来说,当您编写 时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意味着什么?使用引用重载,您将引用(内存位置)返回到数组的第一个元素,它是一个左值。阅读本文可能会帮助您更好地理解它。

于 2020-10-01T19:34:32.783 回答
1

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

如果没有&,您operator[]将返回 的副本(即值)int

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

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

于 2020-10-01T19:49:26.993 回答