参考r值(r值的地址)

时间:2017-10-28 18:32:37

标签: c++ rvalue-reference return-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;
}

如果我在上面的评论中所说的错误,请纠正我。

现在我们可以通过对它进行常量引用来延长临时对象的生命周期。

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;
}

问题是:由于我创建了一个应该被销毁的临时对象的常量引用,这是否意味着cout << &y << endl将打印该临时对象的地址,因为引用只是“别名”?那些存储在内存中的临时对象(R值)在哪里(我使用了原始类型int但它可以是类)?

1 个答案:

答案 0 :(得分:2)

正如评论中已经说明的那样,使const引用(或右值引用)指向临时值会将其生命周期延长到引用的那一周。

  

此外,存储在内存中的临时对象(R值)在哪里(i   使用了原始类型int但它可以是类)?

标准未规定。但是,您可以查看最常见的编译器,了解它们将执行的操作。从GCC开始,没有任何优化,你将得到

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

因此返回值被推入函数内部的EAX寄存器中,一旦返回,该值就被推送到main()的堆栈帧,就像在main函数中创建了变量一样。您将在其他编译器中找到类似的结果。当启用优化时,很明显会发生:编译器看到函数只返回一些常量值并完全忽略它:

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

在这里,我添加了一些printf()调用,它将输出temporty s.t的地址。该计划并非完全无足轻重。 所以它创建了这个函数,但是没有打扰它,只是再次将10写入本地堆栈框架中的某个空间。如果您只是按值使用它,它将被放入寄存器,因为不需要地址。