Задали вопрос на учебе, что больше потребляет ресурсов ++i или i++. Самостоятельно инфо не нашёл, прошу подсказать где искать.
Ответ
Согласно спецификации языка, разница между пре- и постинкрементом состоит в том, что при вычислении выражения значением результат является в одном случае старое, а в другом — новое значение инкрементируемой переменной. В случае простого применения в форме x++; (например, такое часто встречается в циклах) возвращаемое значение не используется, и смысл обеих форм строго одинаков, так что они компилируются в одинаковый объектный код.
Даже если оператор инкремента переопределён, разницы нет, т. к. (в отличие от C++) нет возможности иметь различные определения для пре- и постинкрементов.
Откуда растут ноги у этого вопроса? А вот откуда. В древние времена были наивные компиляторы языка C (и, возможно, C++), которые не умели оптимизировать код. И если они компилировали прямолинейно, то код получался таким:
// x++
int temp = x;
x = x + 1;
// результат = temp; но он не нужен, так что он отбрасывается
и
// ++x;
x = x + 1;
// результат = x; но он не нужен, так что он отбрасывается
Ваш преподаватель, вероятно, слыхал об этом, и ждёт от вас ответа о том, что необходимо ручной оптимизацией убрать ненужную временную переменную. Он неправ, отстал от реальности на вечность и тянет вас в эпоху трилобитов.
В реальности последние как минимум 10 лет компиляторы умеют делать оптимизации намного лучше людей, и в частности прекрасно умеют выбрасывать никому не нужные временные переменные. Так что разницы в сгенерированном коде просто не будет, что можно видеть даже для C++ здесь.* (Если вы, конечно, не отключите оптимизации.)
Теперь с точки зрения промышленной практики. Если вам нужно ускорить выполнение вашей программы, нанооптимизации наподобие использования преинкремента вместо постинкремента — даже если бы они и давали выигрыш в один такт процессора — никогда не являются нужным средством. Оптимизируйте ваши алгоритмы и структуры данных, переходите от квадратичных алгоритмов к линейным и логарифмическим. Не экономьте копейки, это не окупается.
*Например, из таких двух функций:
volatile int x; // угадайте, что будет, если убрать volatile :-P
int pre(int num)
{
for (int i = 0; i < num; ++i)
x = i;
}
int post(int num)
{
for (int i = 0; i < num; i++)
x = i;
}
gcc 7.2 с ключом -O3 производит
pre(int):
test edi, edi
jle .L2
xor eax, eax
.L3:
mov DWORD PTR x[rip], eax
add eax, 1
cmp edi, eax
jne .L3
.L2:
rep ret
post(int):
test edi, edi
jle .L6
xor eax, eax
.L8:
mov DWORD PTR x[rip], eax
add eax, 1
cmp edi, eax
jne .L8
.L6:
xor eax, eax
ret
А с ключом -Os вообще
pre(int):
xor eax, eax
.L3:
cmp eax, edi
jge .L2
mov DWORD PTR x[rip], eax
inc eax
jmp .L3
.L2:
ret
post(int):
jmp pre(int)
Комментариев нет:
Отправить комментарий