2

I'm learning about rvalue references, and the tutorial told me this:

X foo();
X x;
x = foo();

Rather obviously, it would be ok, and much more efficient, to swap resource pointers (handles) between x and the temporary, and then let the temporary's destructor destruct x's original resource.

In other words, in the special case where the right hand side of the assignment is an rvalue, we want the copy assignment operator to act like this.

So, does this mean that return values from functions are always constant by default, and thereby an rvalue? If yes: Are they always constant, or are there exceptions too?

Lightness Races in Orbit
  • 378,754
  • 76
  • 643
  • 1,055
xcrypt
  • 3,276
  • 5
  • 39
  • 63

5 Answers5

3

So, does this mean that return values from functions are always constant by default, and thereby an rvalue? If yes: Are they always constant, or are there exceptions too?

No. They are rvalues iff they don't return a reference type (cv T& or cv T&&). They are constant iff their return type is const-qualified.

That means a return value from a function X foo() is an rvalue (prvalue, if you want new standardese), and not a constant. Moreover, in an expression like x = foo(), we usually don't care if the temporary changes during the assignment which is pretty much the idea behind move-semantics.

jpalecek
  • 47,058
  • 7
  • 102
  • 144
3

Rvalue-ness and constant-ness are not synonyms, but rather a bit orthogonal. With the following definitions:

struct X {};
const X x;
const X f();
int X();

We can categorize the following expressions:

x;       // constant lvalue
f();     // constant rvalue
g();     // non-constant rvalue

As of your particular question: no, not all rvalue expressions are constant.

David Rodríguez - dribeas
  • 204,818
  • 23
  • 294
  • 489
  • Wow, I always learned that whatever cannot be the left hand side of the assignment operator, is an rvalue. Is this statement correct? Because I suppose x cannot be the left hand side of an assignment op? – xcrypt Dec 11 '11 at 22:18
  • 4
    @xcrypt: that's not correct for C++. An lvalue is something you can take the address of. And rvalues are something you can't take the address of. – R. Martinho Fernandes Dec 11 '11 at 22:24
  • @xcrypt: The *can be at the left hand side of an assignment* is a simplification of what lvalue/rvalue mean. There are other different simplifications, I tend to like the object/value distinction:, an lvalue refers to an *object*, while the rvalue is the *value* that it holds. You cannot assign to a *value*, but you cannot assign to a constant object either. Even here, this is also a slight simplification. – David Rodríguez - dribeas Dec 11 '11 at 22:24
  • @xcrypt: No, that is just a mnemonic and original (naming) motivation. It doesn't hold that sharply even in C, yet in C++. – jpalecek Dec 11 '11 at 22:26
  • @DavidRodríguez-dribeas So where do I find the correct explanation? – xcrypt Dec 11 '11 at 22:26
  • 2
    @xcrypt: In the current standard, of course :) (google for C++0x drafts). Section 3.10 is called *Lvalues and rvalues* and has a taxonomy with the definitions of what lvalue, rvalue, xvalue, glvalue and prvalue are... *lvalue* is said to refer to an object or function, and an *rvalue* is an *xvalue* or a temporary or subobject thereof, or a value that is not associated to an object, where *xvalue* is an *lvalue* from which the contents can be moved – David Rodríguez - dribeas Dec 11 '11 at 22:38
  • @Johannes: Right, and [here](http://stackoverflow.com/questions/2169932/) is why. – fredoverflow Dec 12 '11 at 09:45
  • Where is `g` defined here? – Silidrone Mar 13 '23 at 09:13
2

§5.2.2/10 (in N3225) states:

A function call is an lvalue if the result type is an lvalue reference type or an rvalue reference to function type, an xvalue if the result type is an rvalue reference to object type, and a prvalue otherwise.

Philipp
  • 48,066
  • 12
  • 84
  • 109
  • interesting... But what's the difference between a function type and an object type, exactly? – xcrypt Dec 11 '11 at 22:43
1

You might be confusing types, objects and expressions. Only expressions have a notion of lvalue/rvalueness. The expression foo(); is an rvalue of type X. As such, the statement x = foo(); will invoke -- if possible -- the member function X::operator=(X &&) of x. Failing that, it will bind to the standard X::operator=(X const &), since rvalues bind to const-references.

Note that it is possible in theory to have constant rvalues, for example if you had a function declared as X const bar();. Then bar() would not bind to X&&, but only to X const && (as well as to X const &). There is no use for this in practice, though.

Kerrek SB
  • 464,522
  • 92
  • 875
  • 1,084
1

See this previous question, which tells us that neither are rvalue expressions neither implicitly of a const type, nor are the objects they represent made inherently immutable.

However, it is undefined (or forbidden — I forget which) in some cases to modify an object through an rvalue. This does seem to yield a sort of conditional inherent immutability to objects accessed through an rvalue, and the result of evaluating a function call is often — though not always! — an rvalue expression.

Community
  • 1
  • 1
Lightness Races in Orbit
  • 378,754
  • 76
  • 643
  • 1,055