Search code examples
c++classmethodspass-by-referencederived-class

Call member object from object, ERROR: initial value of reference to non-const must be an lvalue


I have the classes Game, Room, Chest and Inventory.

Game contains a Room object and a doSomething() function.

Room contains a vector of Chest objects, a method addChest (which adds a chest to chests vector), and a method getChest that returns a chest from chests vector (given index).

Chest contains an Inventory object.

There's also an open() function that takes as argument an Inventory object by reference.

In the doSomething() function, I add a chest to room1 and call the open() function with as argument the inventory from room1's chest I just added.

Just writing the code below gives an error in open(this->room1.getChest(0).inventory);

#include <vector>

using namespace std;

class Inventory {

};

class Chest {
public:
    Inventory inventory;
};

class Room {
    vector<Chest> chests;
public:
    Room();

    inline void addChest(Chest chest) { this->chests.push_back(chest); }
    inline Chest getChest(int index) { return this->chests[index]; }

};

class Game {
    Room room1;
public:
    void doSomething();
};

void open(Inventory &inventory) {
    //Inventory management
}

void Game::doSomething() {
    Chest chest;
    this->room1.addChest(chest);
    open(this->room1.getChest(0).inventory); //Error here: initial value of reference to non-const must be an lvalue
}

int main() {
    Game game;
    game.doSomething();

    return 0;
}

I don't understand why this error happens. However, I know that if I add a & after Chest in getChest() the error disappears.

What's wrong with the original code? / What other ways of fixing it are there?


Solution

  • What other ways of fixing it are there?

    Changing the prototype of the open method, to this:

    void open(const Inventory &inventory)
    

    Or changing the getChest method to this, as @1201ProgramAlarm commented:

    Chest& getChest(int index)
    

    which will reference the object stored in the vector.

    The error occurs because what the programmer attempts to do indicates an upcoming a logical error, since the method expects a mutable lvalue reference, but you are passing a temporary object.

    Read more in Why can an rvalue not bind to a non-const lvalue reference, other than the fact that writing to a temporary has no effect?


    Not the cause of the error, but here is a tip for you:

    You don't need to use this pointer in your code. I suggest you read about this (again). When should I make explicit use of the `this` pointer?