3

I was experimenting with the different value categories introduced with C++11, before I tried a line of code which in my mind doesn't make sense, but compiled anyway with no warnings:

#include <iostream>

using namespace std;

class A
{
public:
int val;
   A() : val(10) {}
   A(const A& other) : val(other.val) {}
   A(A&& other) : val(other.val) {}
};

int main()
{
   A& a = A();
   cout << a.val << endl; // prints '10'
   return 0;
}

The line which concerns me:

A& a = A();

Now, from what I understand (which is probably wrong), A() is a prvalue. In my mind, this means it is a temporary which has no lifetime beyond the expression it appears in.

Does this not mean that the reference type a should not be able to bind to it?

I've looked around hard and can't find anywhere where this behaviour is stated to be correct, which is understandable as it doesn't make conceptual sense (to me, at least). The reference type a is certainly referencing something, since I can access val as normal.

So my question is, is this code non-standard and only valid according to VS, or is there something here that I've completely misunderstood (which is likely)?

Fear Senpai
  • 41
  • 1
  • 4
  • you forgot to show how `val` is declared – sp2danny Sep 12 '15 at 22:12
  • 1
    neither clang nor gcc [will have it](http://coliru.stacked-crooked.com/a/bb655968d6054b02) – sp2danny Sep 12 '15 at 22:16
  • Could it be that a copy-constructor is called to create A& a? What will happen if the copy-constructor is made private (thus disabling the default copy-constructor too)? – Mike Bessonov Sep 12 '15 at 22:24
  • @MikeBessonov : no, references are created by copying an address. No form of constructor is needed. References are defined in the standard in terms of an *alias*, i.e. a new name for an existing thing. It does not change the total number of `A` objects, so no constructor. – sp2danny Sep 12 '15 at 22:33
  • @sp2danny : yes, you are right, this is what the standard implies. But in this case A& a would be left pointing to an address of the stack which does not contain a valid object anymore. – Mike Bessonov Sep 12 '15 at 22:40
  • _"Also, I couldn't tag prvalue because its not already a tag, sorry."_ None of those tags were useful anyway, so don't apologise for not being able to add another. – Lightness Races in Orbit Sep 12 '15 at 22:49
  • @LightnessRacesinOrbit sorry for some reason none of the tags I put it originally went through. – Fear Senpai Sep 12 '15 at 23:06
  • @Fear: Look at the edit history. I removed them. Please stop adding pointless tags that nobody is ever going to search for. – Lightness Races in Orbit Sep 12 '15 at 23:13
  • 2
    @FearSenpai: If you turn up the warning level to `/W4` the compiler emits this warning "warning C4239: nonstandard extension used: 'initializing': conversion from 'A' to 'A &'" – Blastfurnace Sep 12 '15 at 23:23

0 Answers0