#include<iostream.h>
int main()
{
int m = 2;
int &x = m++;
cout<<m;
return 0;
}
this code should gives
OUTPUT:
3
but this code gives error:
invalid initialization of non-const reference of type 'int&' from a temporary of type 'int'.
Post increment operator returns a temporary object with the value of m before increment.
Non const lvalue references can't be bound to temporary objects. Thus, the compiler rightfully complains.
m++ has to increase m (as a side effect), but evaluate to the original value. It does that by returning a temporary variable holding the value of m before increment.
An non-const l-value reference cannot bind to a temporary object.
You could write:
int &x = ++m;
This works because the pre–increment operator has to return the value after the increment, thus being able to evaluate to an l-value reference to m.
But I wouldn’t recommend that for clarity sake.
You can't use post increment to assign references - it is a temporary object
Here
int &x = m++;
you are assigning a temporary object (right side) to a reference(left side) which doesnt make any sense.
Instead,write:
int &x = ++m;
Related
Recently I was studying lvalue and rvalue concept.
When I do
int&z = 0 ;
I get an expected error like :
initial value of reference to non-const must be an lvalue
However, when I do this with a function that returns lvalue reference like:
int& get_value(){
static int x = 10;
return x;
}
//This line turns out to be valid...
get_value() = 20;
I wonder why get_value() = 20; is valid.
The error message makes it quite clear:
initial value of reference to non-const must be an lvalue
(emphasis mine). So long as the reference is initially bound to an l-value, everything is fine (so long as you don't use a reference to a stack local variable, of course). The reference returned from get_value is bound to x which is an l-value, and that's allowed.
Without the function, you are essentially writing:
int x = 10; // x is an l-value
int &get_x = x; // just a variable instead of a function
get_x = 20; // assignment is ok
which is clearly ok.
What's the difference between the following two assignments?
#include<iostream>
using namespace std;
int main(){
int a=10,i=0;
++i = a //COMPILES WITHOUT ERROR
i++ = a //GIVES AN ERROR LVALUE NEEDED
}
Why does the second assignment produce error?
++i returns the new value of i after the incrementation. That value is an lvalue, called i in this case. Modifying i is certainly allowed.
But i++ returns the old value of i before the incrementation. That value is an rvalue, i.e. an unnamed temporary value. Modifying an rvalue is not allowed in C++.
Pre-increment operation returns its argument (i) already incremented by one. The returned thing is a variable and you can assign to it.
Post-increment returns an old value of i - an rvalue, that cannot be assigned to.
See this question for implementation of operator++ in C++.
Code:
void test(int&& a)
{
a++;
std::cout << a << std::endl;
}
and execute:
test(0);
why output 1? Cause I think 0 is rvalue, it could not be changed.
If you bind a non-class, non-array prvalue, such as a numeric literal, to a reference, the reference will actually be bound to a temporary variable which is a copy of the original value. That is,
int&& a = 0;
creates a temporary int object with the value zero, and then binds a to that.
When you call test(0), the same rule applies, and the reference parameter is bound to a temporary; the temporary is incremented and you get the result 1. Of course you are not incrementing 0 itself.
Both rvalue references and lvalue references to const can bind to a temporary. The difference is, the former is modifiable, the latter is not.
int& i = 0; // invalid
const int& i = 0; // valid
++i; // invalid
int&& i = 0; //valid
++i; // valid;
I am reading the Wikipedia page about references.
It contains the following code:
int& preinc(int& x)
{
return ++x; // "return x++;" would have been wrong
}
preinc(y) = 5; // same as ++y, y = 5
I did try to compile using return x++; instead of return ++x;. As predicted, this led to the following error:
error: invalid initialization of non-const reference of type ‘int&’
from a temporary of type ‘int’
I don't understand this error. I have the vague intuition that the incrementation of x happens too late (i.e., after the function call of preinc is over). However, I don't see how this is a problem since the variable x never ceases to exist. Any explanation is welcome.
The cause of the error is that post increment x++ returns a temporary value, and this cannot be bound to a non-const lvalue reference. This is a simplified version of the same problem:
int i = 42;
int& j = i++; // Error: i++ returns temporary value, then increments i.
const int& k = i++; // OK, const reference can bind to temporary.
The preincrement (++i) does the increment and then return a reference to the variable (Wich have been modified). Postincrement (i++) computes the result of the increment, stores it in a temp local variable, and return a copy of that result after it does the increment. This is done to make look that the increment is done after the call:
int operator++(int)
{
int tmp( *this );
++(*this);
return tmp;
}
This code is for learning purposes, is not real code (int is not a class). Is for showing how postincrement works.
So, as you can see, i++ returns a copy, not a reference. So you cannot initialize the return value, because its a rvalue, not a reference to an existing variable.
you could try to increment x before returning it and see if it solves the problem
int& preinc(int& x)
{
x++;
return x; // "return x++;" would have been wrong
}
Why do constant references not behave the same way as constant pointers, so that I can actually change the object they are pointing to? They really seem like another plain variable declaration. Why would I ever use them?
This is a short example that I run which compiles and runs with no errors:
int main (){
int i=0;
int y=1;
int&const icr=i;
icr=y; // Can change the object it is pointing to so it's not like a const pointer...
icr=99; // Can assign another value but the value is not assigned to y...
int x=9;
icr=x;
cout<<"icr: "<<icr<<", y:"<<y<<endl;
}
The clearest answer.
Does “X& const x” make any sense?
No, it is nonsense
To find out what the above declaration means, read it right-to-left:
“x is a const reference to a X”. But that is redundant — references
are always const, in the sense that you can never reseat a reference
to make it refer to a different object. Never. With or without the
const.
In other words, “X& const x” is functionally equivalent to “X& x”.
Since you’re gaining nothing by adding the const after the &, you
shouldn’t add it: it will confuse people — the const will make some
people think that the X is const, as if you had said “const X& x”.
The statement icr=y; does not make the reference refer to y; it assigns the value of y to the variable that icr refers to, i.
References are inherently const, that is you can't change what they refer to. There are 'const references' which are really 'references to const', that is you can't change the value of the object they refer to. They are declared const int& or int const& rather than int& const though.
What is a constant reference (not a reference to a constant)
A Constant Reference is actually a Reference to a Constant.
A constant reference/ Reference to a constant is denoted by:
int const &i = j; //or Alternatively
const int &i = j;
i = 1; //Compilation Error
It basically means, you cannot modify the value of type object to which the Reference Refers.
For Example:
Trying to modify value(assign 1) of variable j through const reference, i will results in error:
assignment of read-only reference ‘i’
icr=y; // Can change the object it is pointing to so it's not like a const pointer...
icr=99;
Doesn't change the reference, it assigns the value of the type to which the reference refers.
References cannot be made to refer any other variable than the one they are bound to at Initialization.
First statement assigns the value y to i
Second statement assigns the value 99 to i
This code is ill-formed:
int&const icr=i;
Reference: C++17 [dcl.ref]/1:
Cv-qualified references are ill-formed except when the cv-qualifiers are introduced
through the use of a typedef-name or decltype-specifier, in which case the cv-qualifiers are ignored.
This rule has been present in all standardized versions of C++. Because the code is ill-formed:
you should not use it, and
there is no associated behaviour.
The compiler should reject the program; and if it doesn't, the executable's behaviour is completely undefined.
NB: Not sure how none of the other answers mentioned this yet... nobody's got access to a compiler?
By "constant reference" I am guessing you really mean "reference to constant data". Pointers on the other hand, can be a constant pointer (the pointer itself is constant, not the data it points to), a pointer to constant data, or both.
As it mentioned in another answers, a reference is inherently const.
int &ref = obj;
Once you initialized a reference with an object, you can't unbound this reference with its object it refers to. A reference works just like an alias.
When you declare a const reference, it is nothing but a reference which refers to a const object.
const int &ref = obj;
The declarative sentences above like const and int is determining the available features of the object which will be referenced by the reference. To be more clear, I want to show you the pointer equivalent of a const reference;
const int *const ptr = &obj;
So the above line of code is equivalent to a const reference in its working way. Additionally, there is a one last point which I want to mention;
A reference must be initialized only with an object
So when you do this, you are going to get an error;
int &r = 0; // Error: a nonconst reference cannot be initialized to a literal
This rule has one exception. If the reference is declared as const, then you can initialize it with literals as well;
const int &r = 0; // a valid approach
First I think int&const icr=i; is just int& icr = i, Modifier 'const' makes no sense(It just means you cannot make the reference refer to other variable).
const int x = 10;
// int& const y = x; // Compiler error here
Second, constant reference just means you cannot change the value of variable through reference.
const int x = 10;
const int& y = x;
//y = 20; // Compiler error here
Third, Constant references can bind right-value. Compiler will create a temp variable to bind the reference.
float x = 10;
const int& y = x;
const int& z = y + 10;
cout << (long long)&x << endl; //print 348791766212
cout << (long long)&y << endl; //print 348791766276
cout << (long long)&z << endl; //print 348791766340