Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

error: invalid initialization of non-const reference of type ‘int&’ from an rvalue of type ‘int’

Wrong form:

int &z = 12;

Correct form:

int y;
int &r = y;

Question:
Why is the first code wrong? What is the "meaning" of the error in the title?

like image 403
Aquarius_Girl Avatar asked Nov 28 '11 08:11

Aquarius_Girl


4 Answers

C++03 3.10/1 says: "Every expression is either an lvalue or an rvalue." It's important to remember that lvalueness versus rvalueness is a property of expressions, not of objects.

Lvalues name objects that persist beyond a single expression. For example, obj , *ptr , ptr[index] , and ++x are all lvalues.

Rvalues are temporaries that evaporate at the end of the full-expression in which they live ("at the semicolon"). For example, 1729 , x + y , std::string("meow") , and x++ are all rvalues.

The address-of operator requires that its "operand shall be an lvalue". if we could take the address of one expression, the expression is an lvalue, otherwise it's an rvalue.

 &obj; //  valid
 &12;  //invalid
like image 120
BruceAdi Avatar answered Oct 29 '22 07:10

BruceAdi


int &z = 12;

On the right hand side, a temporary object of type int is created from the integral literal 12, but the temporary cannot be bound to non-const reference. Hence the error. It is same as:

int &z = int(12); //still same error

Why a temporary gets created? Because a reference has to refer to an object in the memory, and for an object to exist, it has to be created first. Since the object is unnamed, it is a temporary object. It has no name. From this explanation, it became pretty much clear why the second case is fine.

A temporary object can be bound to const reference, which means, you can do this:

const int &z = 12; //ok

C++11 and Rvalue Reference:

For the sake of the completeness, I would like to add that C++11 has introduced rvalue-reference, which can bind to temporary object. So in C++11, you can write this:

int && z = 12; //C+11 only 

Note that there is && intead of &. Also note that const is not needed anymore, even though the object which z binds to is a temporary object created out of integral-literal 12.

Since C++11 has introduced rvalue-reference, int& is now henceforth called lvalue-reference.

like image 22
Nawaz Avatar answered Oct 29 '22 08:10

Nawaz


12 is a compile-time constant which can not be changed unlike the data referenced by int&. What you can do is

const int& z = 12;
like image 10
Michael Krelin - hacker Avatar answered Oct 29 '22 08:10

Michael Krelin - hacker


Non-const and const reference binding follow different rules

These are the rules of the C++ language:

  • an expression consisting of a literal number (12) is a "rvalue"
  • it is not permitted to create a non-const reference with a rvalue: int &ri = 12; is ill-formed
  • it is permitted to create a const reference with a rvalue: in this case, an unnamed object is created by the compiler; this object will persist as long as the reference itself exist.

You have to understand that these are C++ rules. They just are.

It is easy to invent a different language, say C++', with slightly different rules. In C++', it would be permitted to create a non-const reference with a rvalue. There is nothing inconsistent or impossible here.

But it would allow some risky code where the programmer might not get what he intended, and C++ designers rightly decided to avoid that risk.

like image 5
curiousguy Avatar answered Oct 29 '22 08:10

curiousguy