C++ 返回对局部或临时变量的引用
请看下面的代码。我知道它不会返回局部变量的地址,但为什么它仍然有效并将main()中的变量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()
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