С++ 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 более медленным, чем для старой школы? Я действительно хочу услышать ответ на этот вопрос, потому что мои глаза честно предпочитают цикл, основанный на диапазонах, и мне не хотелось бы выяснять, что цикл, основанный на диапазоне, в два раза медленнее.
Ответы
Ответ 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 для предоставления этой рекомендации]