2013-04-07 2 views
25

Я пишу игру с использованием функций SFML и C++ 11, таких как цикл диапазона. При работе на картах плитки я в основном делал класс для каждой плитки карты, легкий класс, который просто содержит свой спрайт, положение и т. Д., А затем создал некоторые вложенные векторы для представления слоев игровой карты.C++ 11: Почему эта петля диапазона уменьшает FPS на 35?

Чтобы оптимизировать процесс рисования тысяч объектов на экране за один раз, я просто рисовал то, что видит игрок. Все прошло хорошо.

У меня есть следующий метод, который делает игровую карту, состояние в основном возвращает истину, если положение плитки находится в пределах границ камеры

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

     } 

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

+4

[Не измеряйте производительность в FPS] (http://www.opengl.org/wiki/Performance#FPS_vs._Frame_Time). – GManNickG

ответ

58

Внешний цикл делает копию каждого вектора, содержащуюся в 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 привязывается к любому из: rvalue reference, reference или const ссылка, в зависимости от типов, которые возвращает backgroundData. [Hat tip to @Yakk для предоставления этой рекомендации]

+0

Спасибо, что, похоже, сделал трюк. Любое более глубокое объяснение того, почему использовать последнее? –

+6

@ Zamri: Предполагая, что вы имеете в виду «зачем использовать const-ref вместо ref», он добавляет в документацию кода и, возможно, оптимизацию, чтобы заметить, что этот цикл не будет изменять ни один из векторов и будет только смотреть на них. –

+0

@AndreKostur Спасибо! –

Смежные вопросы