20

In this question we've learnt that RVO cannot be applied to an expression like p.first.

In comments it was also suggested that RVO is generally not applied to an expression like r after a declaration like auto& r = p.first. It is less clear whether the standard mandates this behaviour.

in a return statement in a function with a class return type, when the expression is the name of a non-volatile automatic object (other than a function parameter or a variable introduced by the exception-declaration of a handler ([except.handle])) with the same type (ignoring cv-qualification) as the function return type, the copy/move operation can be omitted by constructing the automatic object directly into the function's return value

In the following code, is r a name of the object also known as o, to the extent that RVO is permissible when it forms the expression in a return statement?

int o = 42;
int& r = o;
Community
  • 1
  • 1
Lightness Races in Orbit
  • 378,754
  • 76
  • 643
  • 1,055
  • 2
    `r` is not the name of an object, but the name of a reference (it doesn't help that the Standard calls `int &r` and `void(&r)()` an "object declaration" here, but still). – Johannes Schaub - litb Oct 27 '15 at 15:21
  • @ᐅJohannesSchaub-litbᐊ: Your comments on the other thread were very insightful; would you consider moulding them into an answer for this one? – Lightness Races in Orbit Oct 27 '15 at 15:24
  • Compare also to the description of `decltype`: "if e is an unparenthesized id-expression or an unparenthesized class member access ([expr.ref]), decltype(e) is the type of the entity named by e.". The notion "named by ..." "name of ..." etc is used to refer to a name lookup result. You don't want `decltype(r)` to be `int` – Johannes Schaub - litb Oct 27 '15 at 15:27
  • I don't think an expression is a name (so std text is gibberish); what matters is that an expression designates an object at runtime. – curiousguy Oct 28 '15 at 14:20
  • 2
    @curiousguy an expression is not a name, but a name is an expression (although it its equivalence relation comprises more than that for certain form of names, their textual representation certainly is an expression, so the Standard's text is alright in that regard :p). – Johannes Schaub - litb Oct 30 '15 at 09:49

1 Answers1

18

CWG #633 addressed the fact that references, unlike objects, didn't have actual names. It was resolved by N2993, which extended the notion of a variable to encompass references, thereby giving them names.
Now [basic]/6 reads (all emphasis by me):

A variable is introduced by the declaration of a reference other than a non-static data member or of an object. The variable's name denotes the object or reference.

The name of a reference denotes that variable - the reference - not the object that the reference refers to. Although references are commonly explained as being "other names of objects/functions", in standard terms that definition is plain wrong.

I.e. copy elision is not applicable in your example.


Since the above paper was not adopted until 2009, and you tagged : One can consider the paper as a retrospective correction of C++03. However, in C++03, strictly speaking, a reference is not an entity (this was rectified by CWG #485) and therefore the identifier in its declaration is never treated as a name (see [basic]/4, a name must denote a label or entity) - hence copy elision doesn't apply, again.

Columbo
  • 60,038
  • 8
  • 155
  • 203
  • 1
    Would you say that the [non-normative] note in `[dcl.ref]` (_"A reference can be thought of as a name of an object"_) is now misleading/confusing and should be removed? – Lightness Races in Orbit Oct 27 '15 at 16:07
  • 2
    @LightnessRacesinOrbit I believe that it's a sensible explanation for beginners. However, such explanations have no place in a standardization document, IMHO. There are quite a few such "beginner" explanations scattered throughout - the mnemotechnic verse that I find particularly funny: *"When writing a specialization, be careful about its location; or to make it compile will be such a trial as to kindle its self-immolation."* (normative wording in 14.7.3/7). – Columbo Oct 27 '15 at 16:15
  • 3
    I only saw the first sentence in my SO notifications box, and was all ready to come here and slap you upside the face with a wet trout for suggesting that the ISO C++ standard is suitable for beginners in the first place :) – Lightness Races in Orbit Oct 27 '15 at 16:33
  • @LightnessRacesinOrbit That wouldn't be particularly nice, especially considering that I'm allergic to seafood :-P (ps: what does the wetness have to do with this? :D) – Columbo Oct 27 '15 at 16:36
  • 2
    @Columbo: http://www.urbandictionary.com/define.php?term=trout+slap (SFW as long as you don't scroll down too far) – Lightness Races in Orbit Oct 27 '15 at 17:07
  • 1
    I'm wondering, what harm *would* be allowing the name of the reference variable to be a "name" of the object? In this particular case, where you return a reference to a local storage object by name, elision or implicit move seems about as harmless as it usually is. I cannot think of a construct that makes it horribly broken; incredibly difficult for the compiler sometimes, but not broken. I guess the move (when elision fails) is mandated? ... ok, that could make the compiler die a horrible death: the reference is *maybe* to a local. – Yakk - Adam Nevraumont Oct 27 '15 at 18:48
  • @Yakk "return value optimisation" (or "copy elision" or rather "object confusion") is a transformation whose validity is rooted in the non-overlapping useful lifetime of objects, not on details such as the expression used to designate an object. – curiousguy Oct 28 '15 at 14:23
  • 1
    another rather nontechnical text is at 9.1p4: " Such artistry with names can be confusing and is best avoided.", though non-normative :) – Johannes Schaub - litb Oct 30 '15 at 09:51