18

Could someone please explain how to simulate this error? and also what this complains about.

"A non-const reference may only be bound to an lvalue" in C++

Oliver Charlesworth
  • 267,707
  • 33
  • 569
  • 680
Pavan Dittakavi
  • 3,013
  • 5
  • 27
  • 47

2 Answers2

52

An lvalue is, roughly, whatever may be on the left side of an assignment statement. References provide aliases for other objects:

std::string s;
std::string & rs = s;  // a non-const reference to s
std::string const & crs = s; // a const reference to s

Given the above definitions, referring to rs or crs is the same as referring to s, except that you cannot modify the referred string through crs, as it is const. A variable is an lvalue, so you are allowed to bind a non const reference to it. In contrast you can bind const references to temporary values as in:

std::string const & crs1 = std::string();

However the following is illegal:

std::string & rs1 = std::string();

This is because using non-const references you imply that you want to modify the referenced object. However temporaries bound to references are destroyed when the reference go out of scope. As it is not always intuitive when C++ creates temporary objects, binding them to non-const references has been disallowed, to avoid you the unpleasant surprise of changing your object as you like, just to see it destroyed a few statements later.

Nicola Musatti
  • 17,834
  • 2
  • 46
  • 55
  • @Nicola, one question here. int method1( int & a); Now, does the same apply for thsi one too? – Pavan Dittakavi Aug 06 '11 at 16:18
  • Absolutely. One direct consequence is that you cannot call this function passing an integer literal as argument. – Nicola Musatti Aug 06 '11 at 16:29
  • 1
    @Nicola: Actually, I have always found the restriction quite arbitrary. It is at odds with the fact that you may call a non-const method on a temporary object for example, or that const methods may actually modify mutable attributes... – Matthieu M. Aug 06 '11 at 17:41
  • @Matthieu M.: Well, I can see myself getting fooled once in a while if it was possible to bind temporaries to non const references, but you're right, this situation is inconsistent. Apparently for this reason some standardization committee members wanted to prohibit calling non const member functions on temporaries. – Nicola Musatti Aug 06 '11 at 17:51
  • 1
    @Matthieu: it's not wholly consistent, but I think it makes sense in view of the fact that implicit conversions are applied to function arguments but not to the LHS of a member function call. So, if a non-const reference could be bound then `void increment(long &i) { ++i; }` would ruin your day then point and laugh if you accidentally put the name of an `int` variable as the argument. However, if type X converts to type Y, and type Y has a non-const member function `increment`, there is no equivalent danger of you writing `X x; x.increment();` and then wondering why `x` was unchanged. – Steve Jessop Aug 06 '11 at 18:14
  • ... so it's "safe" for the language to allow member function calls on temporaries, but "unsafe" to allow temporaries as non-const reference arguments. That said, it's a judgement call in the first place to say that passing a reference to the result of a conversion is (a) unlikely to be what was wanted, and also (b) so bad to be worth the language forbidding it, at the cost of forbidding certain things that do make sense: `std::ofstream("filename") << "hello\n"` is allowed, but `std::ofstream("filename") << Foo();` arbitrarily isn't, since the relevant `operator<<` must be a non-member. – Steve Jessop Aug 06 '11 at 18:31
10

It means you can't do something like this:

void foo(int &x) { ... }
int bar()        { ... }

foo(bar());

You would need to make foo take a const reference, or assign the result of bar() to a variable, and then pass that into into foo.

Oliver Charlesworth
  • 267,707
  • 33
  • 569
  • 680