Оценка состояния цикла
Просто быстрый вопрос.
У меня есть цикл, который выглядит так:
for (int i = 0; i < dim * dim; i++)
Является ли условие в цикле for переопределенным в каждом цикле?
Если да, то было бы более эффективно делать что-то вроде этого:
int dimSquare = dim * dim;
for (int i = 0; i < dimSquare; i++)
Спасибо
-Faken
Ответы
Ответ 1
В общем случае, если вы, например, измените значение "dim" внутри вашего цикла, оно будет переучитываться каждый раз. Но, поскольку в вашем примере это не так, достойный компилятор оптимизирует ваш код, и вы не увидите никакой разницы в производительности.
Ответ 2
Да, семантически это будет оцениваться в каждом цикле. В некоторых случаях компиляторы могут удалять условие из цикла автоматически, но не всегда. В частности:
void foo(const struct rect *r) {
for (int i = 0; i < r->width * r->height; i++) {
quux();
}
}
Компилятор не сможет переместить умножение в этом случае, так как для всего, что он знает, quux()
изменяет r
.
В общем, обычно только локальные переменные имеют право снимать выражения из цикла (если вы никогда не принимаете их адрес!). Хотя в некоторых случаях члены структуры могут также иметь право на участие, существует так много вещей, которые могут заставить компилятор предположить, что все в памяти изменилось - например, запись в любой указатель или вызов практически любой функции. Поэтому, если вы используете какие-либо нелокальные объекты, лучше всего предположить, что оптимизация не произойдет.
В общем, я бы рекомендовал проактивно вывести потенциально дорогостоящий код из условия, если он:
- Не мешает читаемости сделать это
- Очевидно, что потребуется очень много времени (например, доступ к сети)
- Или отображается как "горячая точка" при профилировании.
Ответ 3
компилятор будет прекомпутеровать значение Dim * Dim до начала цикла.