C++11: pourquoi cette boucle de plage diminue-t-elle FPS de 35?

J'écris un jeu en utilisant des fonctionnalités SFML et c++11, telles que la boucle de plage. Lorsque je travaille sur des cartes de tuiles, j'ai essentiellement créé une classe pour chaque tuile de carte, une classe légère qui contient simplement son sprite, sa position et autres, puis construit des vecteurs imbriqués pour représenter les couches de carte de jeu.

Afin d'optimiser le processus de dessin des milliers d'objets sur l'écran à la fois, je dessinais simplement ce que le joueur voit. Cela s'est bien passé.

J'ai la méthode suivante cela rend la carte du jeu, la condition renvoie essentiellement true si la position de la tuile est dans les limites de la caméra

void gameMap::render(sf::RenderWindow &winMain, sf::Vector2f offset) {
      for(vector<int> vec1 : backgroundData)
           for(int i : vec1)
              if(collides(i.pos, offset)
                 myWindow.draw(i.sprite);

     }

Cela fonctionne très bien, mais dans le jeu, je reçois 30 FPS à peu près, et beaucoup de mouvement brutal. Mais ce qui me surprend, c'est que le code ci-dessous fait la même chose, rend la même quantité de sprites de tuiles, mais fonctionne à 65 fps et le mouvement est parfaitement lisse

void gameMap::render(sf::RenderWindow &winMain, sf::Vector2f offset) {
          for(int i = 0; i < backgroundTiles.size(); i++)
               for(int j = 0; j < backgroundTiles[i].size(); j++)
                  if(collides(backgroundTiles[i][j].pos, offset)
                     myWindow.draw(backgroundTiles[i][j].sprite);

         }

Pourquoi cela se produit-il? La boucle basée sur la plage C++11 est-elle beaucoup plus lente que l'ancienne l'école pour? Je veux vraiment entendre une réponse à cela, parce que mes yeux préfèrent honnêtement la boucle basée sur la gamme, et je détesterais découvrir que la boucle basée sur la gamme est deux fois plus lente.

25
demandé sur Andy Prowl 2013-04-07 20:55:30

1 réponses

La boucle externe fait une copie de chaque vecteur contenu dans backgroundData:

  for(vector<int> vec1 : backgroundData)

Changez cela pour l'un des éléments suivants:

  for(vector<int>& vec1 : backgroundData)
  for(const vector<int>& vec1 : backgroundData)

Cela rendra vec1 en référence les vecteurs, par opposition à un copie. Puisque les vecteurs sont coûteux à copier, alors que les références sont peu coûteuses à utiliser, cela améliorera considérablement les performances.

Quant au choix entre non - const et const référence, j'utiliserais ce dernier chaque fois que je le peux.

Un plus général consiste à écrire

  for(auto&& vec1 : backgroundData)

Cela crée une référence automatiquement typée vec1 à n'importe quel type backgroundData contient. && dans ce contexte, vec1 se lie à l'une des références: rvalue, reference ou const reference, en fonction des types que backgroundData renvoie. [Chapeau à @Yakk pour avoir fourni cette recommandation]

58
répondu NPE 2013-04-09 05:40:19