假设我有这样的代码: -
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是实际的对象而不是对象的引用?我在网站上已经阅读了一些答案,但我仍然无法完全理解它。
答案 0 :(得分:2)
如果您打印出相同的地址,这只意味着重复使用内存空间,并不意味着它们是相同的对象。
如果添加用户定义的构造函数(和析构函数),您将看到构造(和销毁)5个不同的对象:
struct myStruct{
myStruct() { std::cout << "ctor\n"; }
~myStruct() { std::cout << "dtor\n"; }
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
答案 1 :(得分:1)
对象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;
}
对于使用堆栈的编译器(实现细节,标准不要求),在一次迭代结束和下一次迭代开始之间,附加变量很可能不会放在堆栈上。这可以解释你看到所有对象具有相同的地址。
答案 2 :(得分:0)
这是否实际上在堆栈上创建了5个不同的对象 ?
是的,它确实会创建5个不同的对象。它是否在堆栈上创建它是另一回事。 所有它说的是,在for
循环的每次迭代中,将静态创建一个新对象。现在,当静态创建一个对象时,它具有预定义的范围和生命周期,该范围由编译时间本身。对于实例myStruct obj;
,范围为for
循环。在每次迭代中是否为实例获取相同或不同的地址是实现定义的。
此外,每个对象都有自己的身份,可以通过新创建的事实进行验证(如其他答案中所指定)。此外,此标识是由对象的范围,生命周期,名称组合定义的。现在,此标识不能是该对象的地址。