0

I am trying to pass in the memory address of the mpuTest class property to the fsVar.initialize() method, but I get this error:

main.cpp:38:42: error: taking address of rvalue [-fpermissive]
   38 |     fsVar.initialize(&test3Var.getMpuTest());

I have done a little reading and have learned that an rvalue is something that may not have storage or memory associated with it, like a simple integer. I also know that an lvalue is something that is stored in memory with an address, like a variable.

But I have noticed with the below code that if I have a getter in a class for a property of that class, and I try and use that return value's memory address with &, it will give me the above error. If you don't understand this example please view the below code example.

#include <iostream>

using namespace std;

class mpu {
public:
    void printSomething() {
        cout << "Hi" << endl;
    }
};

class fs {
private:
    mpu* t1;
public:
    void initialize(mpu *mpuPtr) {
        this->t1 = mpuPtr;
    }
    
    void printSomething2() {
        this->t1->printSomething();
    }
};

class Test3 {
private:
    mpu mpuTest;
public:
    mpu getMpuTest() {
        return mpuTest;
    }
};

int main()
{
    Test3 test3Var;
    fs fsVar;
    fsVar.initialize(&test3Var.getMpuTest());
    fsVar.printSomething2();
    return 0;
}

3 Answers3

2

The issue here is that getMpuTest() returns a copy of mpu. And as the copy is not stored to a named variable (or lvalue), it is a temporary (or rvalue). Taking the memory address of a temporary is not allowed because as you correctly said in the question: "an rvalue is something that may not have storage or memory associated with it, like a simple integer."

To correct the code, save the result of test3Var.getMpuTest() to a local variable (because a local variable always has an address) and then pass the address of the local variable to your fsVar.initialize() function.

The correct code would be:

int main()
{
    Test3 test3Var;
    fs fsVar;
    mpu mpuVar = test3Var.getMpuTest();
    fsVar.initialize(&mpuVar);
    fsVar.printSomething2();
    return 0;
}

EDIT: Note this code will make a copy of the test3Var's mpu. If the intention was to pass the address of the original mpu not the copy, you should instead make the getMpuTest() function return a reference as pointed out in other answers and comments: mpu& getMpuTest() { ... }

Karmo
  • 141
  • 1
  • 7
1

The reason why you are getting this error is because test3Var.getMpuTest() is is returning by value, not by reference. When you return an object by value, a temporary - an rvalue - copy of the object is created. Hence the error message talks about rvalue:

main.cpp:38:42: error: taking address of rvalue [-fpermissive]
   38 |     fsVar.initialize(&test3Var.getMpuTest());

The & operator in C++ is only valid for lvalues - objects that have a memory location, not for rvalues (temporary objects), which is why the compiler is giving you this error.

Solution is to return by reference:

mpu& getMpuTest() {
    return mpuTest;
}
marcinj
  • 48,511
  • 9
  • 79
  • 100
0
mpu getMpuTest()

The return type of this function is not a reference. A call of such function is always an rvalue.

return mpuTest;

You're not returning an lvalue that refers to the member. You're returning a rvalue that is a copy of the member.

In order for the function call expression to be an lvalue, the return type must be an lvalue reference.


I have done a little reading and have learned that an rvalue is something that may not have storage or memory associated with it

Pretty much.

like a simple integer

An rvalue doesn't have to be a simple type like an integer; It can be a class type. And conversely, simple integers can have storage.

eerorika
  • 232,697
  • 12
  • 197
  • 326