对象列表中的变量重置问题

Variable resetting problem in a list of objects

今天我正在编写一些 SDL C++ 程序,其中包含称为粒子的正方形。我的问题是,出于某种原因,class Particle 实例中的变量 y 在将其递增 1 后始终重置为传递给构造函数的值。我将对象存储在列表中。 这是每帧调用的方法:

void everyFrame(){
   this->y+=1;
   std::cout<<"update y: "<<this->y<<std::endl;
}

而且这个方法也是每帧调用,在everyFrame()方法之后:

void blit(){
   this->rect.x=this->x*10;
   this->rect.y=this->y*10;
   std::cout<<"blitting y: "<<this->y<<std::endl;
   SDL_BlitSurface(this->image,NULL,screen,&this->rect);
}

这是代码的一部分,我在其中添加了一个 object/objects 到列表中:

std::list<Particle> particles;
particles.push_back(Particle(2,10,5));

我在主循环中执行了这两个方法:

for(Particle x:particles){
   x.everyFrame();
}
for(Particle x:particles){
   x.blit();
}

将 y 5 传入构造函数时程序的控制台输出为:

update y: 6
blitting y: 5

绕了一圈。 我还发现,当我将对象存储在普通变量中而不是列表中时,它就可以工作了。列表中是否有任何 reason/fix 不起作用?

这些行:

for(Particle x:particles){
   x.everyFrame();
}

不是修改particles列表。 这是因为 Particle x:particles 在调用 x.everyFrame() 之前创建每个元素的副本。 您需要将其更改为:

for(Particle & x:particles){  // NOTE: added &
   x.everyFrame();
}

引用列表元素将修改列表中的元素。
这同样适用于应用 blit().

的第二个循环

旁注:
在这种情况下,通常建议使用 auto 关键字。您需要记住 auto 不包括 CV 限定符,并且 pointerness/referenceness。因此你需要:

for(auto & x:particles){ ... }

并且如果你是在不修改元素的情况下遍历容器,建议使用:

for(auto const & x:particles){ ... }