首页 > 解决方案 > 不将函数的返回值分配给变量的含义

问题描述

我正在做一些介绍性的 C++ 练习,其中之一是:运行这段代码后屏幕上会出现什么:

int& testMethod (int& a){

    int c = a+a;
    return c;
};

int main() {
    int z = 5;
    int* y = new int (testMethod(z));
    int r = 25;
    testMethod(r);
    std::cout<<*y;
    return 0;
}

我的问题是:

  1. 我是对的,这是 UB 的一个示例,因为testMethod第二次调用返回的值没有分配给变量吗?
  2. 返回值虽然没有分配给变量,但是否仍然可以恢复,但这取决于?

对于第 2 点,我只是想确认我对堆栈如何工作的理解,如下所示。当一个函数返回一个值并且该值被分配给一个变量时,计算的结果首先被存储在堆栈中retval的某个内存位置,然后被分配给该变量,即写入另一个内存位置。然后堆栈指针向上移动(同样,据我了解,堆栈的“顶部”实际上是它的“底部”,因为指针从最大地址移动到最小地址)。但是retval仍然存在一段时间,直到它被另一条数据覆盖(这可能几乎立即发生)。

当我在 SO 上寻找第一个问题的答案并找到这个线程时,出现了第二个问题,因为两个顶部(通过投票)帖子的答案不同。

标签: c++stackundefined-behavior

解决方案


如何在您的特定平台上实现自动分配无关紧要。您的代码确实testMethod触发了 UB,不是因为您忽略了(顺便说一下,它不是方法)的返回值,而是因为以下行使用了它:

int* y = new int (testMethod(z));

问题是它testMethod总是返回对其局部变量的悬空引用c。使用此引用来初始化动态分配的int触发器 UB。

可以预见的是,启用警告(您应该始终这样做)会产生以下结果:

warning: reference to stack memory associated with local variable 'c' returned [-Wreturn-stack-address]

推荐阅读