Почему есть разница между «++ i»? и «i ++» в цикле?

Мне кажется, что

for(int i = 0; i < 2; i++)

а также

for(int i = 0; i < 2; ++i)

не должен делать то же самое. Для второго примера для меня более логично, что я должен быть равен 1 с начала цикла.

0

Решение

На некоторых процессорах, таких как PDP-11, VAX-11 и 68K, существуют режимы для некоторых инструкций, которые эквивалентны *ptr++ а также *--ptr, В зависимости от того, как именно написан код, компилятору может или не может быть легко использовать эти инструкции — поэтому, используя «правильный» вариант *++ptr или же *ptr++ [что лучше зависит от использования в реальном цикле] внутри цикла может иметь приличную разницу в производительности в этих конкретных случаях. Тем не менее, для ARM и x86 (и я думаю, PowerPC и MIPS, таким образом, охватывающих почти все современные процессоры), этот тип конструкции в любом случае не является частью набора инструкций, и компиляторы в наши дни намного умнее, чем они были, скажем, 10 или 20 лет назад.

Любой разумный компилятор сделает то же самое для основных типов, i++ или же ++i это не проблема.

Если у нас есть «сложный» тип, такой как структура или класс с operator++(int), а также opterator++() может быть небольшая разница [или в крайних случаях большая разница], потому что объект должен быть скопирован. Скажем, у нас есть bigmath класс, и наш i это значение длиной 1000 цифр. Теперь мы должны сделать (n лишнюю) копию 1000 цифр в середине приращения. Если компилятор способен «понять», что происходит, он может удалить эту копию, но это не гарантировано.

4

Другие решения

Мне кажется, что они должны делать то же самое. Оба имеют эффект увеличения i,

Единственная разница заключается в значение выражения; i++ дает значение до приращения, и ++i дает значение после приращения. Но в этом контексте значение отбрасывается, а выражение оценивается только для его побочных эффектов; так что нет никакой разницы в эффекте кода.

В некоторых случаях (если i не int но некоторый пользовательский тип с перегруженным оператором, слишком сложным для понимания компилятором), ++i может быть более эффективным. Это потому что i++ необходимо сделать копию, чтобы вернуть старое значение, в то время как ++i нужно только вернуть ссылку на новое значение. И, конечно же, достаточно безумный определяемый пользователем тип может заставить две перегрузки делать совершенно разные вещи. Но для простых типов там тоже не будет разницы.

3

Хотя ++i а также i++ иметь различную функциональность, когда вы принимаете во внимание возвращаемое значение, в большинстве случаев компилятор оптимизирует i++ в ++i для петель.

Если вы не знаете, в чем разница ++i увеличивает, а затем возвращает значение нового i, в то время как i++ увеличивает, а затем возвращает значение старого i, Бывший технически более эффективный, потому что вам не нужно хранить промежуточное значение, но в целом, они действительно не имеют такой большой разницы, если вы не пытаетесь заниматься гольфом кода и также использовать возвращаемые значения.

2

В вашем примере: нет разница. Если бы тип был определен пользователем, могут быть большие различия.

То, какой из них более логичен, безусловно, является дискуссионным вопросом. Рекомендую вам придерживаться стиля вашей команды или любой другой работы, которая вам подходит.

2

В вашем контексте это то же самое. Разница между ++i а также i++ это порядок операций. Если бы вы были безумным злым программистом C, вы могли бы написать что-то вроде этого:

int i = 3;
if( ++i++ == 4 )
printf( "%d\n", i);

который бы вывел

5

потому что я буду 4 во время теста if, но 5 сразу после теста.

Но не делай этого.

1

Мой лектор очень старался объяснить это классу в моем первом семестре. Из того, что я помню, я почти уверен, что все входы и выходы в основном связаны с возвращаемым значением, например:

++Я буду увеличивать значение i и возвращать увеличенное значение до тех пор, пока операция не завершится, тогда как, хотя i ++ также будет увеличивать значение, если переменная вызывается во время операции, она возвращает неинкрементное значение.

Так что, если у вас было это:

a = 1;
b = ++a;
c = 10;
d = c++;

тогда значения будут

a = 2
b = 2
c = 11
d = 10

(d — это потому, что c был возвращен с ‘post’ ++ ‘, а не с обычными’ pre ‘++’).

В цикле это не имеет абсолютно никакого значения, потому что приращение находится в операторе цикла, а не в операциях после него. Единственный раз, когда это будет иметь значение

for(i = 0; i<5;)
printf("%d ",++i);

где значение 0 не будет напечатано, а значение 5 будет, потому что оно увеличивается во время операции печати.

Ясно, как грязь, а ?? Не спрашивайте меня, почему это было запрограммировано в C! На мой взгляд, это кажется излишним, и то, что так редко появляется в любой программе, которая нуждается в этом, может обойти проблему с помощью одной дополнительной строки кода, изменяющей значение в другой переменной!

0

в вашем случае это то же самое, так как возвращаемое значение вашего выражения не используется.

0
По вопросам рекламы [email protected]