Reference to r-value ( address of r-value )

173 views Asked by At

Consider we have a function that returns by value:

int func() {
   int x = 10; // create local variable x with value of 5
   return x;  // create temporary copy of x which is returned, local variable x is destroyed
}

int main()
{
  int y = func(); // temporary copy of x is copied to y, when it hits`;` the temporary object is destroyed
  return 0;
}

Correct me if I'm wrong in something what i said in comments above.

Now we can extend the life time of temporary object just by making a constant reference to it.

int main()
{
  const int & y = func();  // now the temporary object (R-value) is not destroyed when it hits `;` thus the life time is lenghtened.
  return 0;
}

The question is: Since I created a constant reference to temporary object which should be destroyed, does it mean that cout << &y << endl will print the address of that temporary object since reference is just "alias" ? Also where are those temporary objects (R-values) stored in memory( i used primitive type int but it could be class )?

1

There are 1 answers

0
Jodocus On

As already stated in the comments, making a const reference (or rvalue reference) point to a temporary extends its lifetime to that one of the reference.

Also where are those temporary objects (R-values) stored in memory( i used primitive type int but it could be class )?

This is not specified by the standard. However, you can just check on the most common compilers on what they will do. Starting out with GCC, without any optimizations, you will get

func():
  push rbp
  mov rbp, rsp
  mov DWORD PTR [rbp-4], 10
  mov eax, DWORD PTR [rbp-4]
  pop rbp
  ret
main:
  push rbp
  mov rbp, rsp
  sub rsp, 16
  call func()
  mov DWORD PTR [rbp-12], eax
  lea rax, [rbp-12]
  mov QWORD PTR [rbp-8], rax
  mov eax, 0
  leave
  ret

https://godbolt.org/g/8wPQqx

So the return value is pushed into EAX register inside the function and once it returns, the value is pushed onto the stack frame of main(), just as if you had created the variable in the main function. You will find similar results with other compilers. When turning on optimizations, well, the obvious will happen: the compiler sees the function just returns some constant value and elides it out entirely:

func():
  mov eax, 10
  ret
.LC0:
  .string "%i"
main:
  sub rsp, 24
  mov edi, OFFSET FLAT:.LC0
  xor eax, eax
  lea rsi, [rsp+12]
  mov DWORD PTR [rsp+12], 10
  call printf
  xor eax, eax
  add rsp, 24
  ret

Here, I added some printf() call that will output the address of the temporty s.t. the program is not totally trivial. So it creates the function, but won't bother calling it and just writes 10, again, to some space in the local stack frame. If you just use it by value, it will be just put into a register as no address is required.