user14248283
user14248283

Reputation:

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

Let's say I have this simple container 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];
    }
//--------------------------------------------
};

Specifically

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

I have overloaded the [] operator to get the subscript, I am just learning about operator overloading and container classes.

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

32

The code compiles and executes as expected, but if I remove the & from the function, making it

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

The compiler throws an error

lvalue required as left of operand assignment

Why does this error occur, what is the significance of & in the function?

Upvotes: 0

Views: 67

Answers (2)

Remy Lebeau
Remy Lebeau

Reputation: 595712

The & in int& means that your operator[] returns a reference (ie, an alias, usually implemented as a memory address) to an int variable. Once bound to a variable, any value that is assigned to a reference gets assigned to the variable it refers to.

Without the &, your operator[] would return a copy (ie, the value) of the int instead.

When a function returns a value rather than a reference, the compiler creates a temporary variable to hold that value. That temporary exists only until the end of the statement that creates it. That temporary variable is known as an rvalue, ie a value that is used on the right-hand side of an assignment. To preserve the value longer, the caller must assign it to another variable.

Things like named variables, references to variables, etc are lvalues, ie they can used on the left-hand side of an assignment. An rvalue cannot be used on the left-hand side, only on the right-hand side.

Upvotes: 1

NotAProgrammer
NotAProgrammer

Reputation: 598

Without the reference in the subscript operator overload, you are returning a temporary rvalue from the function. An rvalue cannot occur on the left side of an assignment operation.

Specifically, when you write arr[0], without the reference in your overload that would just return an integer (as whatever the value of arr[0] is).

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

The 5 is an rvalue that cannot be assigned to - what would 5 = 32 mean? With the reference overload, you are returning a reference (the memory location) to the first element of the array which is an lvalue. Reading this might help you understand it better.

Upvotes: 3

Related Questions