67

I see code on StackOverflow every once in a while, asking about some overload ambiguity with something involving a function like:

void foo(int&& param);

My question is: Why does this even come up? Or rather, when would you ever have "a reference to a reference"? How is that any different from a plain old reference? I've never run across this in real-world code, so I'm curious as to what kind of code would need this.

user541686
  • 205,094
  • 128
  • 528
  • 886

3 Answers3

62

It's a rvalue reference, Bjarne describes it here.

Shameless copying ("quoting"):

The rvalue reference

An rvalue reference is a compound type very similar to C++'s traditional reference. To better distinguish these two types, we refer to a traditional C++ reference as an lvalue reference. When the term reference is used, it refers to both kinds of reference: lvalue reference and rvalue reference.

An lvalue reference is formed by placing an & after some type.

A a; A& a_ref1 = a;  // an lvalue reference

An rvalue reference is formed by placing an && after some type.

A a; A&& a_ref2 = a;  // an rvalue reference

An rvalue reference behaves just like an lvalue reference except that it can bind to a temporary (an rvalue), whereas you can not bind a (non const) lvalue reference to an rvalue.

A&  a_ref3 = A();  // Error! 
A&& a_ref4 = A();  // Ok
Skurmedel
  • 21,515
  • 5
  • 53
  • 66
  • 17
    Any idea why anyone would want—let alone need—to use this? – wallyk Apr 08 '11 at 06:02
  • 3
    Search for "perfect forwarding" – Axel Gneiting Apr 08 '11 at 06:06
  • @wallyk: the point is that they'll match temporaries, such that the new C++0x move constructors can know it's safe to have `auto_ptr<>` like semantics, stealing the pointed-to or referenced data from the object being moved (ok as long as it's still left in some valid state for its destructor to run). – Tony Delroy Apr 08 '11 at 06:23
  • 2
    This line A a; A&& a_ref2 = a; doesn't look correct. a is lvalue and lvalue can't be bind to &&. The above line should be expressed as: A a; A&& a_ref2 = std::move(a); or A&& a_ref2 = A(); – Irbis Jul 30 '15 at 09:56
21

It isn't a reference to a reference: such a thing does not exist.

It is an rvalue reference, a new feature added in C++11.

Jimmy T.
  • 4,033
  • 2
  • 22
  • 38
James McNellis
  • 348,265
  • 75
  • 913
  • 977
  • 13
    could you explain the difference? – hhafez Apr 08 '11 at 05:54
  • 1
    References to references certainly do exist in C++, if you think for only a moment you will realize that they have to. Although only the compiler ever has to notate them: users aren't even allowed to write such things in their code (although if they did, it would be written `& &` with a space, not `&&` ... or indeed, `& &&`, `&& &` or other such variations would be okay as well). – Marcel Besixdouze Sep 05 '20 at 19:05
9

It's an rvalue reference. Note that the && token used for Boolean AND and rvalue references, and the & token used for bitwise AND and normal references, are different "words" as far as the language can tell.

An rvalue reference is (usually) bound to an object which may be left in an indeterminate state after the rvalue reference is finished, presumably because the object will then be destroyed.

Simply put, binding a variable to an rvalue reference is the usually the last thing you do to it.

Unlike a regular reference but like a const & reference, an rvalue reference can bind to an rvalue (an expression whose address cannot be directly taken). Like a regular reference but unlike a const & reference, an rvalue reference can be used to modify its object.

Potatoswatter
  • 134,909
  • 25
  • 265
  • 421
  • "indeterminate"'s a little over-stated... it needs to be in a safe state for destruction, but need not retain its earlier value. – Tony Delroy Apr 08 '11 at 06:25
  • @Tony: Yes, indeterminate but valid. A function which accepts an rvalue reference, and modifies it, typically does not specify how the reference is modified. – Potatoswatter Apr 08 '11 at 06:29
  • @Potatoswatter: sorry - I'm still confused by your statements. "typically does not specify how the reference is modified"... assuming by "how the reference is modified" you mean "how the referenced object is modified" (I can't imagine anything else) - the function normally decides exactly that, for example: a move constructor might use `swap` on containers and steal pointers, setting them to NULL in the referenced object.... – Tony Delroy Apr 08 '11 at 06:49
  • @Tony: Yes, that's what I mean. I think of `swap` as more of an implementation detail. For example, I would not use a move constructor and then assume the source object is empty. Nor would I specify the effects of my move constructor on the source object, even if it is predictable. – Potatoswatter Apr 08 '11 at 06:57
  • @Potatoswatter: ahhh, I'm with you now - yes, this is all implementation detail and need not be specified in the interface documentation.... – Tony Delroy Apr 08 '11 at 07:01
  • @Tony is correct that "indeterminate" is a bit too hard, as you could very well try to determine the state afterwards. "Unspecified but valid" is more in line with the standard text. – Bo Persson Apr 08 '11 at 11:06