Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/137.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 返回对局部或临时变量的引用_C++ - Fatal编程技术网

C++ 返回对局部或临时变量的引用

C++ 返回对局部或临时变量的引用,c++,C++,请看下面的代码。我知道它不会返回局部变量的地址,但为什么它仍然有效并将main()中的变量I分配给“6”?如果变量从堆栈内存中删除,它如何仅返回值 #include <iostream> int& foo() { int i = 6; std::cout << &i << std::endl; //Prints the address of i before return return i; } int main()

请看下面的代码。我知道它不会返回局部变量的地址,但为什么它仍然有效并将main()中的变量
I
分配给“6”?如果变量从堆栈内存中删除,它如何仅返回值

#include <iostream>

int& foo()
{
    int i = 6;
    std::cout << &i << std::endl; //Prints the address of i before return
    return i;
}

int main()
{
    int i = foo();
    std::cout << i << std::endl; //Prints the value
    std::cout << &i << std::endl; //Prints the address of i after return
}
#包括
int&foo()
{
int i=6;

std::cout您很幸运。从函数返回不会立即擦除刚刚退出的堆栈帧


顺便说一句,你是如何确认你得到了6分的?表达式
std::cout必须是你的编译器正在做的事情


确认您的示例将从堆栈内存中删除引用。

当您的函数通过引用返回整数时,它将立即分配给main()中的局部变量“i”。这意味着为foo()分配的堆栈内存必须持续足够长的时间才能执行返回分配。虽然这是一种糟糕的形式,但通常有效。如果您试图保留引用

int &i = foo();

它失败的可能性更大。

返回指向局部变量的引用或指针是未定义的行为。未定义的行为意味着,标准将决定权留给编译器。这意味着,未定义的行为有时工作正常。

main()中,
i
的地址永远不会更改
,但其中包含的值将被删除。您正在获取局部变量的引用,并在该引用超出范围后使用它。(不精确的语言警告)值
6
在堆栈上。由于您在将
6
放在那里之后没有对堆栈执行任何操作,因此对它的引用仍将包含相同的值。因此,正如其他人所说,您很幸运

要想知道有多幸运,请尝试在调用
foo()
后运行此使用堆栈的代码:

…但是当我取消对
post_foo()
的调用的注释并再次运行它时,
6
早已不存在了:

001FFD38 = 6
post_foo() = 310
001FFD38 = 258923464

你很幸运。不要这样做。你可能会发现这很有用:我相信幸运的是,我在foo()中没有改变(它允许编译器将文件放在文本中或某个长期存在的地方,而不是堆栈中)从局部变量获取地址可能会阻止编译器/运行时为其使用寄存器。这会导致性能不佳。当他在main()中打印地址时,会显示6@ San:现在,“dave18编辑了这个问题。对不起,我一定已经读过这个问题:”另外一点,函数调用的后果是编译器依赖的。通常GCC不会修改堆栈上的任何值(因此,我们仍然得到旧值)。但是像DEV C++这样的编译器修改了值。(虽然我看不出它这样做的原因)如果你以后尝试访问任何值,你只会得到一个垃圾值!!@smartmuki:这一点很好!此外,我相信调试编译有时会在执行过程中分割堆栈,以突出对范围外变量的访问。它不能正常工作的机会取决于观看演示的人的重要性。
002CF6C8 = 6
002CF6C8 = 6
001FFD38 = 6
post_foo() = 310
001FFD38 = 258923464