C++:如何在循环中的堆栈上创建对象

C++ : How does creating an object on stack within a loop works under the hood?

本文关键字:堆栈 创建对象 循环 C++      更新时间:2023-10-16

假设我有这样的代码:-

struct myStruct{
    int a;
    int b;
};
int main(){
    for(int i=0; i<5; i++){
        myStruct obj; 
        cout<<"Address of object in memory : "<<&obj<<endl;
    }
    return 0;
}

这实际上会在堆栈上创建 5 个不同的对象吗?如果是这样,为什么考虑到 obj 是实际对象而不是对对象的引用,它每次都打印完全相同的内存地址?我已经在网站上阅读了一些答案,但我仍然无法完全理解它。

如果你打印了相同的地址,那只是意味着内存空间被重用,并不意味着它们是相同的对象。

如果添加用户定义的构造函数(和析构函数(,您将看到构造(和析构(5个不同的对象:

struct myStruct{
    myStruct() { std::cout << "ctorn"; }
    ~myStruct() { std::cout << "dtorn"; }
    int a;
    int b;
};

潜在结果:

ctor
Address of object in memory : 0x7fffc5be8c50
dtor
ctor
Address of object in memory : 0x7fffc5be8c50
dtor
ctor
Address of object in memory : 0x7fffc5be8c50
dtor
ctor
Address of object in memory : 0x7fffc5be8c50
dtor
ctor
Address of object in memory : 0x7fffc5be8c50
dtor

对象

obj在每次迭代开始时创建,并在结束时销毁。

如果将输出语句放在其构造函数和析构函数中,您将能够看到这种情况的发生。 (尽管从技术上讲,如果检测对象存在的唯一方法是跟踪构造函数和析构函数调用,则编译器可以自由地删除对象,但在这种情况下,大多数编译器可能不会,因为替代方法是在每次迭代开始时重新初始化对象(。

您还可以通过添加额外的范围来查看这一点。

int main()
{
   for(int i=0; i<5; i++)
   {
      {   // extra scope here
          myStruct obj; 
          cout<<"Address of object in memory : "<<&obj<<endl;
      }
      obj = something();   //   will not compile since obj does not exist here
   }
   return 0;
}

对于使用堆栈(标准不需要的实现细节(的编译器,在一次迭代结束和下一次迭代开始之间,很有可能不会将其他变量放置在堆栈上。 这可以解释您看到所有具有相同地址的对象。

这实际上会在堆栈上创建 5 个不同的对象吗?

是的,它确实创建了 5 个不同的对象。它是否在堆栈上创建它是另一回事。它所说的只是,在循环的每次迭代中for将静态创建一个新对象。现在,当一个对象是静态创建的时,它有一个预定义的范围和生存期,这是在编译时决定的。对于实例myStruct obj;作用域for循环。在每次迭代中是否为实例获取相同或不同的地址是实现定义的。

此外,每个对象都有自己的身份,可以通过它们是新创建的事实来验证(如其他答案中所述(。此外,此标识由对象的作用域、生存期、名称的组合定义。现在,此标识不能是对象的地址。