Search code examples
c++listsdl

Variable resetting problem in a list of objects


Today I was writing some SDL C++ program, with squares called particles. My problem is that, for some reason, variable y in instances of class Particle is always resetting to the value passed into the constructor after incrementing it by 1. I'm storing the objects in a list.
That's a method that's called every frame:

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

And this method is also called every frame, after the everyFrame() method:

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);
}

This is the part of the code, where I'm adding an object/objects to the list:

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

And there I'm executing these 2 methods in the main loop:

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

The console output of the program when y 5 is passed into the constructor is just:

update y: 6
blitting y: 5

looped around. I also found out that when I'm storing an object in a normal variable, not in a list, then it works. Is there any reason/fix for it not working in a list?


Solution

  • These lines:

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

    are not modifying the particles list. This is because Particle x:particles is creating a copy of each element before calling x.everyFrame(). You need to change it to:

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

    Taking a refernce to the list element will modify the element in the list.
    The same applied to the second loop applying blit().

    A side note:
    Using the auto keywoard is usually recomended in this case. You need to keep in mind that auto does not include CV qualifiers, and pointerness/referenceness. Therefore you need:

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

    And if you are traversing a container without modifying the elements, it is rcomended to use:

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