Пре-инкремент против пост-инкремента

Насколько они разные? Вот что я думаю, но я не уверен....

Если вы используете предварительное приращение, например, в цикле for с ++j, то вы, по сути, говорите: «Сделайте копию значения j для использования в цикле, затем увеличьте j, затем выполните операторы в цикл с копией j." Если вы используете пост-инкремент в том же цикле j++, то вы в основном говорите: «Сделайте копию значения j для использования в цикле, затем пройдите операторы в цикле с копией j, затем увеличивайте Дж."

Причина, по которой я не уверен, заключается в том, что я создал цикл for, который умножает значение j на 10, а затем выводит результат от j=1 до j=12, используя как постинкрементное, так и предварительное приращение. Человекочитаемый вывод точно такой же, как после и до инкремента. Я думаю: «Каким образом результаты будут одинаковыми, если не будет задействована какая-то операция копирования?»

Итак, я предполагаю, что разница между предварительным и последующим инкрементом действительно становится важной в php, когда я использую ссылки (которые действуют как указатели в php), а не имена для возвращаемых значений? Это может быть связано с тем, что копии ссылок не создаются, поэтому предварительное приращение будет выглядеть так: «Увеличить j, затем пройтись по операторам в цикле с измененным значением j, затем снова увеличить j...», тогда как после инкрементация будет выглядеть так: "Используйте значение j для операторов в цикле, затем измените значение j, затем пройдите цикл с новым значением j..."


person Wolfpack'08    schedule 19.06.2011    source источник
comment
Это поведение не зависит от языка (или, по крайней мере, не специфично для PHP), поэтому на самом деле это дубликат Почему изменение приращения pre на post в итерационной части цикла for не имеет значения?   -  person Mark Elliot    schedule 19.06.2011
comment
в дополнение к тому, что говорит отметка, этот вопрос предполагает, что у вас есть довольно фундаментальное непонимание того, что на самом деле делает цикл for... никакого копирования не происходит - 3-й пункт цикла for просто выполняется в конце тела цикла петля. вы можете поставить туда любой статменет, который вам нравится, и никакого специального копирования не произойдет   -  person tobyodavies    schedule 19.06.2011
comment
И никакие ссылки не действуют как указатели.   -  person netcoder    schedule 19.06.2011
comment
@tobyodavies: Хотя я думаю, что недопонимание также связано с тем, как работает инкрементация, я чувствую, что должен также посмотреть поведение зацикливания из-за вашего поста. Спасибо. Любой хороший ресурс? :) Кроме того, я понимаю ваш комментарий ... специального копирования не произойдет из-за ответа другого пользователя, который я выбрал как правильный. Еще раз спасибо.   -  person Wolfpack'08    schedule 22.06.2011
comment
@netcoder: я не согласен, потому что ссылки php 5.3 на самом деле являются указателями.   -  person Wolfpack'08    schedule 22.06.2011
comment
@Fohsap: Нет, все переменные в PHP являются указателями (начиная с PHP4): zval*. Указатель указывает на определенное место в памяти. В PHP такого нет, будь то 5.2 или 5.3. Однако есть ссылки, которые указывают на записи в дереве символов PHP, но вы все равно не можете заставить их указывать на место в памяти по вашему выбору. Итак, опять же, нет, ссылки не являются и не действуют как указатели.   -  person netcoder    schedule 22.06.2011
comment
@netcoder +1 - моя лакмусовая бумажка для ссылок и указателей: можете ли вы выполнить арифметику указателей? в php вы явно не можете.   -  person tobyodavies    schedule 24.06.2011
comment
@netcoder Но в практическом смысле они есть.   -  person Wolfpack'08    schedule 22.02.2013
comment
@MarkElliot У этого есть лучший ответ, и он нацелен на другой стиль обучения.   -  person Wolfpack'08    schedule 22.02.2013


Ответы (3)


Пре- или постинкрементирование не откладывает волшебным образом все на потом. Это просто встроенное сокращение.

введите здесь описание изображения

// pre-increment
$var = 5;
print(++$var); // increments first, then passes value (now 6) to print()

// post-increment
$var = 5;
print($var++); // passes value (still 5) to print(), then increments

Теперь давайте посмотрим на петлю.

for ($i = 0; $i < 9; $i++) {
    print($i);
}

Последняя часть объявления цикла ($i++) — это просто оператор, который должен выполняться после каждого прохождения цикла. Он «передает» значение в никуда, а затем увеличивает его. $i в то время нигде не используется. Позже, когда выполняется следующий оператор (print($i);), значение $i уже увеличилось.

// add 1, then do nothing with $i
for ($i = 0; $i < 9; ++$i) {}

// do nothing with $i, then add 1
for ($i = 0; $i < 9; $i++) {}

Как бы вы это ни делали, $i внутри цикла будет одним и тем же.


Если это поможет, вы можете думать о них как о небольших подпрограммах, которые делают следующее:

// ++$i
{
    $i = $i + 1;
    return $i;
}

// $i++
{
    return $i;
    $i = $i + 1;
}

Когда я перечитал ваш вопрос, я думаю, что путаница больше связана с тем, как работает цикл, чем с тем, как работают операторы приращения. Имея в виду, что приращение — это простая операция «все сразу», вот как работает третье выражение в цикле.

// here's a basic loop
for ($i = 0; $i < 9; $i++) {
    // do loop stuff
    print($i);
}

// this is exactly what happens
for ($i = 0; $i < 9; ) {
    // do loop stuff
    print($i);

    $i++;
}

Тот факт, что эта последняя строка может быть помещена в объявление цикла, не дает ей никаких особых возможностей. Нет никаких ссылок или чего-либо, что использовалось за кулисами. Одна и та же переменная $i видна как внутри, так и вне цикла. Каждый оператор внутри или вне цикла напрямую ищет значение $i, когда это необходимо. Вот и все. Не смешное дело.

person Wiseguy    schedule 19.06.2011
comment
Так что в основном это потому, что это для возвращаемых значений, а не для полученных значений? - person Wolfpack'08; 19.06.2011
comment
@Fohsap Я думаю, вы больше путаетесь с циклом, чем с увеличением. Смотрите мое последнее обновление. Надеюсь, это поможет. - person Wiseguy; 19.06.2011

Выполняя $x++, вы выполняете пост-инкремент... Это означает, что инкремент будет происходить только после того, как оператор будет оценен.

Итак, учитывая следующий код:

$x = 10; $y = 0; $z = 5;

$y = $z * $x++;

PHP делает это:

$x = 10; $y = 0; $z = 5;

$y = $z * $x++;

// Ignore Post-Increment, Evalutate
$y = $z * $x;
$y = 5 * 10;

// Now Increment x - POST-INCREMENT
$x = $x + 1;
$x = 10 + 1;
$x = 11;

// Continue evaluating statement
$y = 5 * 10;
$y = 50;

Выполняя ++$x, вы выполняете предварительное приращение... Это означает, что приращение произойдет до того, как оператор будет оценен:

$x = 10; $y = 0; $z = 5;

$y = $z * ++$x;

// Do Pre-Increment
$x = $x + 1;
$x = 10 + 1;
$x = 11;

// Evaluate
$y = $z * $x;
$y = 5 * 11;
$y = 55;

В случае цикла for в PHP PHP оценивает цикл for следующим образом:

for($i = 0; $i < 30; $i++) {
  doSomething();
}

// Is evaluated EXACTLY as such by PHP

$i = 0;
while($i < 30) {
  doSomething();

  $i++;
}

Первое выражение ($i = 0) оценивается (выполняется) один раз безоговорочно в начале цикла.

В начале каждой итерации оценивается $i < 30. Если он оценивается как TRUE, цикл продолжается, и выполняются вложенные операторы. Если он оценивается как FALSE, выполнение цикла завершается.

В конце каждой итерации $i++ оценивается (выполняется) как независимое выражение.

Поэтому постинкрементное или предварительное инкрементирование переменной в качестве третьего выражения в цикле не влияет на ее поведение. В этом простом случае оба выражения будут вести себя точно так же. то же самое.

Однако в сложном цикле, таком как следующий:

for($i = $j = 0; $i < 30; $i += ++$j) {
  $j = getResult($j);
}

Постинкрементное или предварительное инкрементирование $j напрямую влияет на значение $i в соответствии с приведенными выше примерами. В этом случае вам нужно выбрать именно то, что вы хотите сделать.

person Andrew Moore    schedule 19.06.2011

$i = 0;
echo $i++;
echo $i;
$j=0;
echo ++$j;
echo $j;

Pre increment отображает увеличенное значение. Но значение отображения Post increment затем увеличивается. О коде будут выводиться 01 и 11

person Kaja Mydeen    schedule 29.01.2016
comment
Пожалуйста, будьте более описательными. - person Sajidur Rahman; 29.07.2016