我有下面的代码。

#include <iostream>

int * foo()
{
    int a = 5;
    return &a;
}

int main()
{
    int* p = foo();
    std::cout << *p;
    *p = 8;
    std::cout << *p;
}

并且代码正在运行,没有运行时异常!

输出是58

怎么可能呢?局部变量的内存在其函数之外不是不可访问的吗?


当前回答

从函数返回后,所有标识符都将被销毁,而不是将值保存在内存位置,如果没有标识符,则无法定位值。但该位置仍然包含前一个函数存储的值。

因此,这里函数foo()返回a的地址,a在返回地址后被销毁。您可以通过返回的地址访问修改后的值。

让我举一个真实的例子:

假设一个人把钱藏在一个地方,并告诉你这个地方。过了一段时间,告诉你钱的位置的人死了。但你仍然可以拿到那些隐藏的钱。

其他回答

从函数返回后,所有标识符都将被销毁,而不是将值保存在内存位置,如果没有标识符,则无法定位值。但该位置仍然包含前一个函数存储的值。

因此,这里函数foo()返回a的地址,a在返回地址后被销毁。您可以通过返回的地址访问修改后的值。

让我举一个真实的例子:

假设一个人把钱藏在一个地方,并告诉你这个地方。过了一段时间,告诉你钱的位置的人死了。但你仍然可以拿到那些隐藏的钱。

您实际上调用了未定义的行为。

返回临时作品的地址,但由于临时作品在函数的末尾被销毁,访问它们的结果将是未定义的。

因此,您没有修改a,而是修改了a曾经所在的内存位置。这种差异与崩溃和不崩溃之间的差异非常相似。

它之所以能工作,是因为自从a被放入堆栈以来,堆栈(还没有)被改变过。 在再次访问a之前调用一些其他函数(它们也调用其他函数),你可能不会再那么幸运了……: -)

这是典型的未定义行为,两天前在这里讨论过——搜索一下网站。简而言之,您是幸运的,但是任何事情都可能发生,并且您的代码正在对内存进行无效的访问。

你在编译程序时启用了优化器吗?foo()函数非常简单,可能已经在结果代码中被内联或替换。

但是我同意Mark B的观点,结果行为是不确定的。