在 C++ 或任何其他语言中,我想知道如果一个函数将其范围内的局部变量返回给调用者并将其分配给其他变量,那么语义如何工作?我尝试过的 C++ 示例如下:
代码:
int my(){
int t=10;
cout<<&t<<"\n";
return t;
}
int main() {
const int& c=my();
cout<<&c;
return 0;
}
输出:
0x7fff71249164
0x7fff71249184
在上面的示例中,我认为我是通过引用传递它的,所以输出不应该相同吗?但我只是碰巧获得了不同的输出。另外,我尝试将 my() 的返回类型从
int
更改为 int&
但仍然得到不同的输出。我还尝试使用指针传递,输出也有所不同。我最近刚刚学习 C++,感到很困惑,所以任何帮助将不胜感激。
使用平台:ideone online C++ (gcc 8.3)
我期望在我所有的实验中,我会得到相同的打印值,并且地址也相同。但我有什么遗漏的吗?
my
返回按值,而不是按引用。
调用具有非引用返回类型的函数的函数调用表达式(例如
my()
)是 纯右值表达式。
当您使用纯右值表达式初始化引用变量(例如
c
)时,将从纯右值具体化一个临时对象,并且引用将绑定到该临时对象。临时对象使用纯右值表达式的值进行初始化,并赋予与引用相同的(扩展)生命周期,即临时对象一直存在到引用范围结束为止。
这个临时对象通常是与属于
t
变量的对象不同的对象。因为它们是不同的对象,所以它们不需要具有相同的地址。另一方面,由于 t
的生命周期在函数 my
返回时结束,因此编译器也可以自由地将临时对象放置在 t
对象所在的同一内存位置。在这种情况下,地址将是相同的。 (其实细节更复杂,但结果是一样的。)
此外,编译器可以应用所谓的“命名返回值优化”(NRVO),它允许编译器将临时对象和 t
视为引用
same对象,从而跳过任何复制否则是必要的。在这种情况下,地址也可以相同。编译器不会对类型
int
执行此操作,但可能对更复杂的类型执行此操作。