7

In my effort to understand rvalue references, I have been pondering when the compiler will determine that a particular function argument is an rvalue reference, and when it will determine it to be an lvalue reference.

(This issue is related to reference collapsing; see Concise explanation of reference collapsing rules requested: (1) A& & -> A& , (2) A& && -> A& , (3) A&& & -> A& , and (4) A&& && -> A&&).

In particular, I have been considering if the compiler will always treat unnamed objects as rvalue references and/or if the compiler will always treat temporary objects as rvalue references.

In turn, this leads me to question whether unnamed objects are equivalent to temporary objects.

My question is: Are unnamed objects always temporary; and are temporary objects always unnamed?

In other words: Are unnamed objects and temporary objects equivalent?

Community
  • 1
  • 1
Dan Nissenbaum
  • 13,558
  • 21
  • 105
  • 181
  • I don't know the technical terminology well enough to post as an answer, but I think this is a counter-example: `void foo(int) {}`. Here the parameter is an object that is not temporary, but has no name. – GManNickG Dec 05 '12 at 18:14
  • Good point. This example seems to make clear that it is *temporary* objects that are relevant to rvalue references - not so much *unnamed* variables. – Dan Nissenbaum Dec 05 '12 at 18:19
  • Is there actually a definition for "unnamed object?" – Nikos C. Dec 05 '12 at 18:26
  • 1
    I would like to know the definition of "temporary object" (as well...) – Dan Nissenbaum Dec 05 '12 at 18:29

3 Answers3

3

I might be wrong, since I'm not sure what the definition of "unnamed object" is. But consider the argument of the foo() function below:

void foo(int)
{ /* ... */ }

int main()
{ foo(5); }

foo()'s argument is unnamed, but it's not a temporary. Therefore, unnamed objects and temporary objects are not equivalent.

Nikos C.
  • 50,738
  • 9
  • 71
  • 96
3

Temporary objects can be named.

Very common case - when passed as a parameter to a function. Another less common case - binding a const reference to an rvalue result of a function.

int f(int i) { return i + 1; }
int g() { const int &j = f(1); return j; }

Unnamed objects are often temporary, but not always. For example - anonymous union object:

struct S
{
   union { int x; char y; };
} s;

And, of course, any object created by operator new.

Perhaps there are other cases, but even only these can serve as counterexamples to the hypothesis :)

chill
  • 16,470
  • 2
  • 40
  • 44
2

I have been pondering when the compiler will determine that a particular function argument is an rvalue reference, and when it will determine it to be an lvalue reference.

I assume you are talking about function templates with universal reference parameters, like this?

template<typename T>
void foo(T&& t)
{
}

The rules are very simple. If the argument is an rvalue of type X, then T will be deduced to be X, hence T&& means X&&. If the argument is an lvalue of type X, then T will be deduced to be X&, hence T&& means X& &&, which is collapsed into X&.

If you were really asking about arguments, then the question does not make much sense, because arguments are never lvalue references or rvalue references, because an expression of type X& is immediately converted to an expression of type X, which denotes the referenced object.

But if you actually meant "How does the compiler distinguish lvalue arguments from rvalue arguments?" (note the missing reference), then the answer is simple: the compiler knows the value category of every expression, because the standard specifies for every conceivable expression what its value category is. For example, the call of a function is an expression that can belong to one of three value categories:

X   foo();   // the expression foo() is a prvalue
X&  bar();   // the expression bar() is an lvalue
X&& baz();   // the expression baz() is an xvalue

(Provided, of course, that X itself is not a reference type.)

If none of this answers your question, please clarify the question. Also, somewhat relevant FAQ answer.

Community
  • 1
  • 1
fredoverflow
  • 256,549
  • 94
  • 388
  • 662
  • Quick follow-up: Suppose you have `int x; int & y = x;` What is the type of `y` considered to be - `int` or `int &`? – Dan Nissenbaum Dec 05 '12 at 20:22
  • The answer depends on who you are talking to and what language feature you are currently considering :) For example, both `decltype(y)` and `decltype((y))` are `int&`, but I think `decltype` is the only case where the type of something is considered to be a reference. Correct me if I'm wrong! The standard says "If an expression initially has the type “reference to T” (8.3.2, 8.5.3), the type is adjusted to T prior to any further analysis. The expression designates the object or function denoted by the reference, and the expression is an lvalue or an xvalue, depending on the expression." – fredoverflow Dec 05 '12 at 20:30
  • `auto&&` and `T&&` can also deduce types as references. – Puppy Dec 05 '12 at 20:33
  • 1
    Re. my previous comment: i.e., given `class A; void foo(A&& a_); int main() { foo(A()); }` - the *parameter* type is an **rvalue reference**, the *argument type* corresponding to `A()` is an **rvalue**, and the *argument type* corresponding to `a_` is (interestingly) an **lvalue**, correct? – Dan Nissenbaum Dec 05 '12 at 20:33
  • 1
    You must be careful not to confuse types with value categories. The parameter *type* is `A&&` (an rvalue reference to A), and the parameter *value category* is lvalue. All parameters are lvalues, regardless of their type, because all parameters have names, and most names are lvalues. The argument *type* is `A`, and the argument *value category* is prvalue. – fredoverflow Dec 05 '12 at 20:42
  • 1
    Following up... I very highly recommend @FredOverflow's linked article (at the bottom of his answer); it's outstanding, and (despite his comment that it's "somewhat relevant", which he probably wrote since he himself wrote the article in the link so he's being understated), it covers the entire topic in detail. – Dan Nissenbaum Dec 05 '12 at 22:39