25

我正在使用 SFML 和 C++11 功能(例如范围循环)编写游戏。在处理瓦片地图时,我基本上为每个地图瓦片创建了一个类,一个简单地包含其精灵、位置等的轻量级类,然后构建了一些嵌套向量来表示游戏地图层。

为了优化一次在屏幕上绘制数千个对象的过程,我只是简单地绘制玩家所看到的。这进展顺利。

我有以下渲染游戏地图的方法,如果平铺位置在相机边界内,则条件基本上返回 true

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

     }

它工作得很好,但是在游戏中我得到了大约 30 FPS,并且有很多粗糙的动作。但令我惊讶的是,下面的代码做了同样的事情,渲染了相同数量的瓷砖精灵,但运行速度为 65 fps,并且运动非常流畅

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

         }

为什么会这样?C++11 基于范围的循环比老派慢得多吗?我真的很想听听这个问题的答案,因为老实说,我的眼睛更喜欢基于范围的循环,而且我不想发现基于范围的循环慢两倍。

4

1 回答 1

58

外部循环正在复制包含在中的每个向量backgroundData

  for(vector<int> vec1 : backgroundData)

将其更改为以下任一项:

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

这将成为对 vectorvec1引用,而不是copy。由于向量的复制成本很高,而引用的使用成本很低,这将显着提高性能。

const至于非参考和参考之间的选择const,我会尽可能使用后者。

一个更一般的选择是写

  for(auto&& vec1 : backgroundData)

vec1这会创建一个对包含的任何类型的自动类型引用backgroundData&&在这种情况下,最终会vec1绑定到以下任何一个:右值引用、引用或const引用,具体取决于backgroundData返回的类型。[@Yakk 提供此建议的提示]

于 2013-04-07T16:58:22.317 回答