
 Understanding lvalues and rvalues in C and C++ - wglb
http://eli.thegreenplace.net/2011/12/15/understanding-lvalues-and-rvalues-in-c-and-c/
======
bjoernbu
Really awesome writeup. Easy to understand, very clear and full of valueable
information. However, I really wonder aout one thing (not just because of this
artcle but it reminded me):

When exactly are move semantics and rvalue references useful, APART from using
functions that return complex types. I am currently working on a codebase and
I am really unsure if move semantics are something I really want to use. Sure,
I'd love them for new projects, but if there are naming conventions and even
conventions of passing result objects by pointer, not by reference (not my
favourite rule), I don't think I'd like mixing styles. I think differently
about starting to use "auto" and lambdas, but this is not about C++11 in
general.

So actually I really wonder if there is a just case of rvalue references other
than move constructors and returning by value. Any pointers?

~~~
Someone
A good attempt, but I spot an error:

"They’re not lvalues because both are temporary results of expressions, which
don’t have an identifiable memory location (i.e. they can just reside in some
temporary register for the duration of the computation)."

The problem is that lvalues _can_ "just reside in some temporary register for
the duration of the computation". Any decent optimizing compiler will treat
simple loop counters that way.

I am not even sure the C++ standard even mentions registers.

~~~
qdog
Maybe 'register' wasn't abstract enough, he means something like (in psuedo-
assembly):

    
    
      ldr r1,4     ;Load constant 4 into register 1
      add r2,r2,r1 ;Add contents of r2 and r1, store in r2
      ldr r1,5     ;Load constant 5 into register 1
    

where the value is only temporarily available for the single calculation. Even
without thinking of registers, you can refer to the loop variable, but you
can't refer to numbers in your operations.

Maybe he could update this line for clarity, though.

------
simias
It's a good article, however I've always thought lvalue meant "left-value"
(i.e. a value that can appear as the left part of an assignment) but this
article says it stands for "locator value". Who's right? And then what does
rvalue stand for if not "right-value"? Register value? I find no definite
answer on Google.

~~~
Sharlin
As the article points out, the original meaning of the "l" in "lvalue" indeed
was "left". However, in C and C++ there are lvalues that cannot appear as the
left-hand-side of assignment (const variables, arrays, functions) and rvalues
that can (in C++ you can say, for example, C() = C(); for some class C because
the assignment operator is just a member function, and member functions can be
called for rvalues.)

What more accurately grasps the definition of lvalues and rvalues in C and C++
standards is that the former have an individual identity (concretely, they are
permitted as the operand of the address-of operator &) and the latter don't.
(Except don't get me started on the fact that in C++ one can overload
operator&...)

------
jpdoctor
Terrible start point:

 _An lvalue (locator value) represents an object that occupies some
identifiable location in memory (i.e. has an address)._

 _rvalues are defined by exclusion, by saying that every expression is either
an lvalue or an rvalue._

So a pointer represents "an object that occupies some identifiable location in
memory", meeting his definition of lvalue, and yet is a perfectly valid
rvalue.

I sentence this person to be a teaching assistant for one term.

Edit: I _love_ the first two replies to this comment:

1\. _No, lvalues are never rvalues by definition._

2\. _all lvalues are rvalues,_

~~~
Sharlin
No, lvalues are _never_ rvalues by definition. In the C and C++ language
standards, rvalues and lvalues are not defined based on which side of the
assignment operator they may appear on. The assignment operator takes an
rvalue as its right operand, however, lvalues are also accepted there because
there's an implicit lvalue-to-rvalue conversion taking place, as pointed out
later in the article.

------
apaprocki
Move semantics opens up a new age where higher level STL-like containers (and
types built from them) can perform as well as raw C pointer based
implementations. The last real roadblock is the elephant in the room: compiler
support. I've argued with John Lakos that all the guys at work on the C++
committee should take a break from the standards process now and devote
themselves for a time to getting C++11 fully supported into all main
compilers. Only having move semantics in gcc is not good enough :/

~~~
shin_lao
It's there in clang and Visual Studio 2010.

~~~
apaprocki
Only leaving CC (Oracle), xlC (IBM), aCC (HP) to name a few. I got 99
platforms and x86 is only one. :)

~~~
nitrogen
On your large projects that must support Oracle, IBM, and HP's compilers, what
prevents you from compiling your C++11 code with gcc and linking it in? Is it
to difficult to maintain a consistent external ABI? Does gcc not support the
other ABIs and/or mangling conventions?

~~~
lysium
Mangling is not standardized and every compiler does it differently. In
general, you can't link files compiled by different C++ compilers.

~~~
apaprocki
And to make things even more fun, each individual compiler usually comes with
baggage it has collected over the years. In xlC alone the -qnamemangling
option can be set to: ansi (don't let it fool you), v11, v10, v9, v8, v7, v6,
v5, v4, v3, or compat so even code build with the same compiler isn't always
compatible.

------
msarnoff
Interesting C++ tidbit: the ternary operator can yield an lvalue, like so:

    
    
      int foo = 0, bar = 0;
      (cond ? foo : bar) = 8;
    

This doesn't work in plain C.

~~~
koenigdavidmj
But it does with pointers in C:

    
    
      int foo = 0, bar = 0;
      *(cond ? &foo : &bar) = 8;

