Подтвердить что ты не робот

С++ 11: Почему эта петля диапазона уменьшает FPS на 35?

Я пишу игру с использованием функций SFML и С++ 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 кадров в секунду, и движение идеально плавное

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

         }

Почему это происходит? Является ли цикл на основе С++ 11 более медленным, чем для старой школы? Я действительно хочу услышать ответ на этот вопрос, потому что мои глаза честно предпочитают цикл, основанный на диапазонах, и мне не хотелось бы выяснять, что цикл, основанный на диапазоне, в два раза медленнее.

4b9b3361

Ответ 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)

Это создает автоматически типизированную ссылку vec1 для любого типа backgroundData. && в этом контексте заканчивается тем, что vec1 связывается с любым из: справочной ссылки r reference, ссылки или const, в зависимости от типов, возвращаемых backgroundData. [Hat tip to @Yakk для предоставления этой рекомендации]