2

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

考虑这段代码:

#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的堆栈以供新的使用?

4

1 回答 1

0

该程序表现出未定义的行为。在proxyreturnsmt中,您绑定middle到一个临时对象。该临时对象的生命周期只会延长到middle超出范围。

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

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

于 2012-04-13T18:12:29.053 回答