从按值返回创建常量左值引用:它是如何工作的

creating const lvalue-reference from return by value: how does it work?

本文关键字:何工作 工作 创建 返回 常量 引用      更新时间:2023-10-16

>我从这里了解到,常量引用可以从函数的值返回的对象中进行。但是现在我问自己:把这个对象放在哪里,这样它就是安全的,不会被未来的函数调用堆栈覆盖?

请考虑以下代码:

#include <iostream>
using namespace std;
struct A{};
A returnsmt(){
    int avariable;
    cout<<"returnsmt stack: "<<&avariable<<endl;
    return A();
}
const A& proxyreturnsmt(){
    int avariable;
    const A& middle=returnsmt();
    cout<<"proxyreturnsmt stack: "<<&avariable<<" A ptr: "<<&middle<<endl;
    return middle;
}
int main(){
    int avariable;
    const A& a=proxyreturnsmt();
    cout<<"main stack: "<<&avariable<<" A ptr: "<<&a<<endl;
}

现在,main甚至不知道它将从堆栈的对象创建引用是不可行的,因此诀窍不能是它将隐藏指针传递给自己的空闲堆栈存储桶。g++ 上的这段代码打印:

returnsmt stack: 0x7fff3718bc0c
proxyreturnsmt stack: 0x7fff3718bc28 A ptr: 0x7fff3718bc2f
main stack: 0x7fff3718bc4c A ptr: 0x7fff3718bc2f

因此,如果堆栈向下增长,则对象所在的位置实际上是proxyreturnsmt堆栈。如果在获得此引用后,您调用(比方说)function_with_big_stack_alloc,并且肯定会回收旧proxyreturnsmt堆栈以供新使用,您为什么不会遇到麻烦?

程序表现出未定义的行为。 在 proxyreturnsmt 中,您将middle绑定到临时对象。 该临时对象的生存期仅延长到middle超出范围。

然后返回对 middle 的引用;但是当函数返回时,它所引用的对象被销毁。 因此,在main中,您将a绑定到调用proxyreturnsmt的结果,a是一个悬空引用(它所引用的对象不再存在)。

当您尝试使用引用(通过获取不再存在的引用对象的地址)时,程序将显示未定义的行为。