【问题标题】:C++11: Why does this range loop decrease FPS by 35?C++11:为什么这个范围循环将 FPS 降低 35?
【发布时间】:2013-04-07 16:55:30
【问题描述】:

我正在使用 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 基于范围的循环比老派慢得多吗?我真的很想听听这个问题的答案,因为老实说,我的眼睛更喜欢基于范围的循环,而且我不想发现基于范围的循环慢了一倍。

【问题讨论】:

标签: c++ performance c++11


【解决方案1】:

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

  for(vector<int> vec1 : backgroundData)

将其更改为以下任一:

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

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

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

一个更通用的替代方法是写

  for(auto&& vec1 : backgroundData)

这将为backgroundData 包含的任何类型创建一个自动类型的引用vec1。 &amp;&amp; 在此上下文中最终使 vec1 绑定到以下任何一个:右值引用、引用或 const 引用,具体取决于 backgroundData 返回的类型。 [感谢@Yakk 提供此建议的提示]

【讨论】:

  • 非常感谢,这似乎已经成功了。关于为什么使用后者有更深入的解释吗?
  • @Zamri:假设您的意思是“为什么使用 const-ref 而不是 ref”,它会添加到代码文档和可能的优化中,以注意此循环不会修改任何向量并且会只是看着他们。
  • 作为替代方案,for( auto&amp;&amp; vec1 : backgroundData ) 为backgroundData 包含的任何类型创建一个自动类型引用vec1。 &amp;&amp; 在这种情况下最终使vec1 绑定到任何右值引用、引用或const 引用,具体取决于backgroundData 返回的类型。如果您正在迭代更烦人的类型的容器,这将更加有用。 :)
  • @Yakk:我冒昧地将您的精彩评论纳入答案。希望你不要介意。谢谢!
  • 当你想修改元素时使用 auto&&。不使用时使用 const auto&。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-02-11
  • 1970-01-01
  • 2018-09-21
  • 1970-01-01
  • 2021-03-07
  • 2020-10-14
相关资源
最近更新 更多