我有以下 C++ 代码,我正在运行 g++ (Ubuntu 7.4.0-1ubuntu1~18.04.1) 7.4.0:
#include <iostream>
const int& getConst() {
int x = 10;
printf("x ptr: %p\n", &x);
const int &y = 10;
printf("y ptr: %p\n", &y);
return y;
}
int main() {
int start = 0;
printf("start ptr: %p\n", &start);
const int &t = getConst();
printf("t: %d\n", t);
printf("t ptr: %p\n", &t);
int end = 0;
printf("end ptr: %p\n", &end);
return 0;
}
这段代码的输出如下:
root@78600f6683dd:/home/test/question# ./a.out
start ptr: 0x7ffdcd2381f8
x ptr: 0x7ffdcd2381c8
y ptr: 0x7ffdcd2381cc
t: 10
t ptr: 0x7ffdcd2381cc
end ptr: 0x7ffdcd2381fc
我对结果有两点感到困惑:
函数
main()
中start
和end
的内存位置分别是0x7ffdcd2381f8和0x7ffdcd2381fc。main
函数变量的内存位置是递增的。 main函数调用了getConst()
函数,但是函数getConst()
中变量的位置是0x7ffdcd2381c8和0x7ffdcd2381cc,与中的变量相比都是递减的>main()
函数。因为main
函数调用getConst()
函数,所以getConst()
的位置不应该在堆栈顶部到main( )
?在
getConst()
函数中,y
是对 10 的 const 引用。据我了解,程序是这样的,一个 临时 int 变量 被创建,值为 10,并且 yreferences
指向它。从程序的输出中可以看出,y
和t
都指向相同的内存位置。但是临时变量是定义在栈中的变量,不是应该在getConst()
函数返回后清理吗?如果是这样,t
怎么还能得到正确的值呢?
最佳答案
您的代码具有未定义的行为,因为它正在返回对临时变量的引用,所以任何事情都可能发生。
然而,实际发生的情况可能是返回的引用基本上是一个指针,指向的内存不再有效,但指针本身只是一个数字,因此您能够打印它的值也就不足为奇了。打印引用的值可能会起作用,因为运行时不会“清理”释放的堆栈内存,这会浪费时间,当内存被重新使用时,它将被重新初始化。如果您调用一个包含未初始化变量的新函数,那么如果它们也具有与 getConst
中设置的值相同的值也就不足为奇了。这当然都是未定义的行为。
传统上堆内存从内存底部增长,栈从顶部增长,当两者相遇时你的程序就内存不足了。对于现代虚拟内存方案,这不再是字面上的情况,但堆栈通常仍然是一个固定大小的内存块,从末尾到前面使用,因此新堆栈分配的地址低于以下地址并不罕见旧的。这就是溢出堆栈变量如此危险的原因,您不是在覆盖未使用的内存,而是在覆盖堆栈中较早的变量。
关于c++ - const 引用的内存位置,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59589197/