为什么不使用 "new" 运算符创建的对象得到相同的地址

Why does the object created without using "new" operator gets the same address

通过 this question,一个答案说创建的对象在其范围之外被销毁,为了清楚地理解这个概念,我编写了以下代码:

#include <iostream>

using namespace std;

struct Node{
    int val;
    Node *next;
    Node(int x) : val(x) , next(NULL){}
};

int main(){
    for(int i=0;i<10;i++){
        int someval = rand()%100;
        Node somenode = Node(someval);
        printf("Address for object %d is %p \n",i+1, &somenode);
    }
}

我得到以下输出:

Address for object 1 is 0x7ffc32ff26b0 
Address for object 2 is 0x7ffc32ff26b0 
Address for object 3 is 0x7ffc32ff26b0 
Address for object 4 is 0x7ffc32ff26b0 
Address for object 5 is 0x7ffc32ff26b0 
Address for object 6 is 0x7ffc32ff26b0 
Address for object 7 is 0x7ffc32ff26b0 
Address for object 8 is 0x7ffc32ff26b0 
Address for object 9 is 0x7ffc32ff26b0 
Address for object 10 is 0x7ffc32ff26b0 

我了解到每次循环迭代并创建新对象时,每个对象都会被销毁;但为什么他们都有相同的地址。我在创建链表时遇到了这个问题,我没有使用 new 运算符来创建对象,而是使用相同的代码,并且列表始终指向相同的节点,我 运行 变成了无限环形。为什么每个对象都分配了相同的地址?

您一直在 stack 的顶部创建对象,然后将其删除(对象在每次循环迭代结束时超出范围,并在下一次迭代之前解构)。因此,每次为对象分配 space 时,堆栈顶部的地址都是相同的。

如果删除循环并连续分配多个 Node,随着堆栈的增长,您会看到每个地址都不同。

这与局部变量和范围有关。由于变量 somenode 是在 for 循环的 {} 括号内声明的,因此它的作用域是 for 循环的局部范围。也就是说,它在 for 循环的单次迭代期间存在,然后在下一次迭代开始之前超出范围。

编译器通常会尽量提高效率。在 for 循环的第一次迭代之后,地址 0x7ffc32ff26b0 指向内存中一个足以存储 Node 结构的位置。编译器也知道这个内存没有被使用(它超出了范围)所以它认为它可以重新使用相同的内存位置。换句话说,虽然这些结构占用相同的RAM内存,但它们都是独立的,彼此无关。

无法保证此行为,您不应依赖它,它只是编译器试图使最终汇编代码尽可能简单和高效的尝试。