В чем разница между ++ $ i и $ i ++ в PHP?

Ответы:

96

++$iявляется предварительным приращением, а $i++пост-приращением.

  • pre-increment: iсначала увеличивает переменную, а затем отменяет ссылку.
  • пост-инкремент: сбросить ссылку, а затем увеличить i

"Воспользуйтесь тем фактом, что PHP позволяет выполнять пост-инкремент ($ i ++) и пре-инкремент (++ $ i). Смысл остается таким же, пока вы не пишете ничего вроде $ j = $ i ++, однако предварительное увеличение происходит почти на 10% быстрее, а это означает, что вам следует переключаться с пост-инкремента на предварительное увеличение, когда у вас есть возможность, особенно в узких циклах и особенно если вы педантичны в отношении микрооптимизации! " - TuxRadar

Для дальнейшего пояснения, пост-инкремент в PHP был задокументирован как хранение временной переменной, которая относится к этим 10% накладным расходам по сравнению с предварительным инкрементом.

jldupont
источник
6
Это общее эмпирическое правило или это специфично для PHP.
Зойдберг
1
... источник указан в моем ответе. Я сам не проверял ... Думаю, я мог бы, просмотрев исходный код PHP ...
jldupont
3
Я бы сам не стал обобщать на какой-то другой язык.
jldupont
3
Увеличение скорости пре-инкремента зависит от PHP из-за того, что пост-инкремент создает временную переменную, создавая накладные расходы.
Кори Баллоу
4
@knittl Помните, что это 10% от (можно надеяться) очень быстрой операции :)
jensgram
68

++$iувеличивается $i, но оценивается как значение $i+1 $i++приращения $i, но оценивается как старое значение $i.

Вот пример:

$i = 10;
$a = $i++;
// Now $a is 10, and $i is 11

$i = 10;
$a = ++$i;
// Now $a is 11, and $i is 11

Иногда требуется небольшая предварительная стоимость использования $i++. Смотрите, когда вы делаете что-то вроде

$a = $i++;

Вы действительно делаете это:

$temporary_variable = $i;
$i=$i+1;
$a=$temporary_variable;
Шалом Краймер
источник
4
Это лучший ответ. Общее обобщение того, что это делает без примеров кода, бессмысленно. Проголосовать за такие ответы, скорее всего, будут те, кто уже знает, как это работает, и поэтому считает их отличными ответами.
Джеймс
Я уверен, что на более низком уровне это еще не все, поэтому этот вопрос может быть спорным. Но зачем PHP нужна временная переменная? Почему бы и нет: $ a = $ i; $ i = $ i + 1;
Тейлор Вэнс,
@Taylor, отличный вопрос! Попробуйте заменить $ i вызовом функции, подобным этому: $a=func()++и спросите себя, как вы могли бы переписать его без ++ и без вызова func () более одного раза.
Шалом Креймер
43

++$i это предварительное приращение

  1. $i увеличивается
  2. возвращается новое значение

$i++ пост-инкрементный

  1. значение $iскопировано во внутреннюю временную переменную
  2. $i увеличивается
  3. $iвозвращается внутренняя копия старого значения
Гамбо
источник
14
++$i //first increment $i then run line
$i++ //first run line then increment $i 
Саджад Бахмани
источник
Технически это упрощение - подумайте о цикле for и т. Д.
Энтони Карти
11

в этом случае разницы нет:

for($i = 0;$i<3;++$i)var_dump $i;
/*
int(0)
int(1)
int(2)
*/
for($i = 0;$i<3;$i++)var_dump $i;
/*
int(0)
int(1)
int(2)
*/

но:

for($i = 0;$i<3; $j = ++$i )var_dump($j);
/*
NULL
int(1)
int(2)
*/
for($i = 0;$i<3; $j = $i++ )var_dump($j);
/*
NULL
int(0)
int(1)
*/
0b10011
источник
Это полезно, приращение префикса, кажется, меньше всего удивляет. Я собираюсь переключиться на постоянное использование префикса.
CMCDragonkai
8

в этом примере просто

<?php 

$x = 10;  

echo $x++. ' '.$x;  // the result is 10 and 11

echo '<br>';

$y = 10;

echo ++$y. ' ' .$y; // the result is 11 and 11

// so the  $x++ is not showing +1 at first but the next time
// and the ++y is showing +1 first time but not increasing next
Ашрафул Алам
источник
Благодарю за простой пример. Теперь я понимаю.
Praditha
7

Разница в том, ++$iчто $iпеременная будет увеличиваться и возвращать обновленное значение, тогда как $i++вернет исходное значение, поэтому увеличивайте его.

$prefix = 1;
$postfix = 1;
echo ++$prefix;   // 2
echo $postfix++;  // 1
Рубенс Фариас
источник
5

Чтобы объяснить точку зрения jldupont:

$i = 1;
$x = $i++;
echo $x; // prints 1
$x = ++$i;
echo $x; // prints 3
Болдевин
источник
4

Другой способ взглянуть на приращение до и после приращения - это сокращение для объединения двух операторов.

Предварительное приращение

// long form
$y = $y + 1;
$x = $y; // any statement using $y

// shorthand
$x = ++$y; // the same statement using $y

Пост-инкремент

// long form
$x = $y; // any statement using $y
$y = $y + 1;

// shorthand
$x = $y++; // the same statement using $y
Майкл
источник
4

$ i ++ известен как постинкремент. Он увеличивает значение $ i только после того, как сначала присваивает исходное значение $ i переменной $ j.

++ $ i называется предварительным приращением. Он увеличивает значение $ i перед присвоением значения $ j, поэтому обновленное значение $ i будет присвоено $ j.

Следовательно,

$i = 4;
$j = $i++;
// Now, $i = 5 and $j = 4

$i = 4;
$j = ++$i;
// Now, $i = 5 and $j = 5

Эти теории аналогичным образом применимы и к декременту.

Надеюсь это поможет!

Таринда Нимнаджит
источник
3

Наверное, лучше всего это проиллюстрировать на примере ...

Пост-инкремент:

$zero = 0;
$n = $zero++; //$n is zero

Предварительное приращение:

$zero = 0;
$n = ++$zero; //$n is one
Brianreavis
источник
3

Краткий ответ:

  • Префикс увеличивает значение и возвращает увеличенное значение
  • Postfix увеличивает значение и возвращает значение до того, как оно было увеличено
  • Префикс быстрее

Длинный ответ: если вы немного подумаете, как бы вы реализовали это самостоятельно, вы, вероятно, поймете, почему префикс быстрее. По правде говоря, постфикс фактически (часто) реализуется с использованием префикса:

const T T::operator ++ (int) // postfix
    {
    T orig(*this);
    ++(*this); // call prefix operator
    return (orig);
    }

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

Я действительно посмотрел это несколько дней назад. Вот мой источник.

Мизипзор
источник
3

Основное назначение оператора приращения после исправления - это использование следующего вида:

while(*condition*)
    $array[$i++] = $something;

Это очень элегантный способ обойти некоторые итерации массива. Сломать:

  1. Переменная $ something будет присвоена элементу массива с индексом $ i
  2. Переменная $ i будет увеличена
  3. Итерация подошла к концу, условие будет проверено

Во всех остальных случаях следует использовать префиксный оператор. Это делает код более понятным (вы можете быть уверены, что уже работаете с увеличенным значением конкретной переменной).

пользователь3554809
источник
Проголосовали за рекомендацию использовать префикс, если только постфикс не нужен.
разработчик
0

Я запустил следующий код, чтобы проверить, работает ли ++ $ i на 10% быстрее, чем $ i ++. Я признаю, что код не дает стабильного результата, но даже тогда я должен был хотя бы увидеть некоторые цифры около 10%. Наивысший результат был примерно 4-4,5%.

<?php

$randomFloat = rand(0, 10) / 10;

$before1 = microtime(true);

for($i=0; $i <1000000; ++$i){
    $rand = (rand(0, 10) / 10) * (rand(0, 10) / 10);
}

$after1 = microtime(true);
echo 'it took '.($after1-$before1) . ' seconds fot ++$i<br />';

$before2 = microtime(true);

for($i=0; $i <1000000; $i++){
    $rand = (rand(0, 10) / 10) * (rand(0, 10) / 10);
}

$after2 = microtime(true);
echo 'it took '.($after2-$before2) . ' seconds fot $i++<br /><br />';

echo '++$i is '.((($after1-$before1)*100)/($after2-$before2)-100).'% faster than $i++';
Waxyen Лен
источник
-1

Оба оператора по-прежнему выполняют то, что подразумевает их синтаксис: увеличивают. Независимо от префикса или постфикса, переменная обязательно будет увеличена на 1. Разница между ними заключается в их возвращаемых значениях.

1. Приращение префикса возвращает значение переменной после того, как оно было увеличено.

2. С другой стороны, более часто используемый постфиксный инкремент возвращает значение переменной до того, как оно было увеличено.

// Prefix increment

let prefix = 1;
console.log(++prefix); // 2

console.log(prefix); // 2

// Postfix increment

let postfix = 1;

console.log(postfix++); // 1

console.log(postfix); // 2

Чтобы запомнить это правило , я думаю о синтаксисе этих двух. Когда вводят приращение префикса, он говорит ++ x. Здесь важна позиция ++. Сказать ++ x означает сначала увеличить (++), а затем вернуть значение x, таким образом, мы имеем ++ x. Постфиксное приращение работает наоборот. Сказать x ++ означает сначала вернуть значение x, а затем увеличить его (++), таким образом, x ++.

Рохит Сайни
источник