Подтвердить что ты не робот

Когда ++ не дает те же результаты, что и +1?

Следующие два фрагмента кода С# производят разные результаты (при условии, что уровень переменной используется как до, так и после рекурсивного вызова). Почему?

public DoStuff(int level)
{
  // ...
  DoStuff(level++);
  // ...
}

public DoStuff(int level)
{
  // ...
  DoStuff(level+1);
  // ...
}

После прочтения некоторых ответов ниже я подумал, что стоит потратить трассировки стека уровня уровня ++, ++ и уровня + 1, чтобы подчеркнуть, как обманывать эту проблему.

Я упростил их для этой публикации. Рекурсивная последовательность вызовов начинается с DoStuff (1).

//level ++

DoStuff(int level = 1)
DoStuff(int level = 2)
DoStuff(int level = 2)
DoStuff(int level = 2)
Уровень

//++

DoStuff(int level = 4)
DoStuff(int level = 4)
DoStuff(int level = 3)
DoStuff(int level = 2)

//уровень + 1

DoStuff(int level = 4)
DoStuff(int level = 3)
DoStuff(int level = 2)
DoStuff(int level = 1)
4b9b3361

Ответ 1

Чтобы прояснить все остальные ответы:

+++++++++++++++++++++

DoStuff(a++);

Является эквивалентным:

DoStuff(a);
a = a + 1;

+++++++++++++++++++++

DoStuff(++a);

Является эквивалентным:

a = a + 1;
DoStuff(a);

+++++++++++++++++++++

DoStuff(a + 1);

Является эквивалентным:

b = a + 1;
DoStuff(b);

+++++++++++++++++++++

Ответ 2

Поскольку первый пример действительно эквивалентен:

public DoStuff(int level)
{  
  // ...
  int temp = level;
  level = level + 1;
  DoStuff(temp);
  // ...
}

Обратите внимание, что вы также можете написать ++ уровень; это будет эквивалентно:

public DoStuff(int level)
{  
  // ...
  level = level + 1;
  DoStuff(level);
  // ...
}

Лучше не злоупотреблять операторами ++ и - на мой взгляд; он быстро запутывается и/или undefined что действительно происходит, и современные компиляторы С++ не генерируют более эффективный код с этими операторами в любом случае.

Ответ 3

уровень ++ пройдет уровень в DoStuff, а затем увеличит уровень для использования в остальной части функции. Это может быть довольно неприятной ошибкой, поскольку рекурсия никогда не закончится (из того, что показано DoStuff, всегда передается одно и то же значение). Возможно, вместо этого используется ++ уровень, поскольку это противоположно level ++ (увеличивает уровень и передает добавленное значение в DoStuff)?

уровень + 1 пройдет уровень + 1 в DoStuff и оставьте уровень без изменений для остальной части функция.

Ответ 4

возвращаемое значение level++ будет level и therefore передать level в DoStuff. Это может быть довольно неприятная ошибка, поскольку рекурсия никогда не закончится (из того, что показано DoStuff, всегда передается с тем же значением). Может быть, вместо ++level или level + 1?

level + 1 пройдет level + 1 в DoStuff и оставит level неизменным для остальной части функции.


Оператор post-increment (переменная ++) точно эквивалентен функции

int post_increment(ref int value)
{
    int temp = value;
    value = value + 1
    return temp;
}

в то время как оператор pre-increment (++) точно эквивалентен функции

int pre_increment(ref int value)
{
    value = value + 1;
    return value;
}

Поэтому, если вы разворачиваете оператор inline в код, операторы эквивалентны:

DoStuff(a + 1)

int temp = a + 1;
DoStuff(temp);

DoStuff(++a)

a = a + 1;
DoStuff(a);

DoStuff(a++);

int temp = a;
a = a + 1;
DoStuff(temp);

Важно отметить, что пост-приращение не эквивалентно:

DoStuff(a);
a = a + 1;

Кроме того, в качестве точки стиля не следует увеличивать значение, если только намерение не должно использовать добавочное значение (определенная версия правила), не присваивайте значение переменной, если вы не планируете использовать это значение "). Если значение i + 1 больше никогда не используется, предпочтительное использование должно быть DoStuff(i + 1), а не DoStuff(++i).

Ответ 5

Первое использует значение в уровне и THEN, вставляя его.

Последний использует уровень + 1 в качестве переданной переменной.

Ответ 6

level++ возвращает текущее значение level, а затем увеличивает level. level+1 вообще не изменяет level, но DoStuff вызывается со значением (level + 1).

Ответ 7

public DoStuff(int level)
{

  // DoStuff(level);
  DoStuff(level++);
  // level = level + 1;
  // here, level value is 1 greater than when it came in
}

Он фактически увеличивает значение уровня.

public DoStuff(int level)
{
  // int iTmp = level + 1;
  // DoStuff(iTmp);
  DoStuff(level+1);
  // here, level value hasn't changed
}

фактически не увеличивает значение уровня.

Не проблема перед вызовом функции, но после вызова функции значения будут разными.

Ответ 8

На уровне ++ вы используете постфиксный оператор. Этот оператор работает после использования переменной. То есть после того, как он помещается в стек для вызываемой функции, он увеличивается. С другой стороны, уровень + 1 является простым математическим выражением, и он оценивается, и результат передается вызываемой функции. Если вы хотите сначала увеличить значение переменной, а затем передать ее вызываемой функции, вы можете использовать префикс operator: ++ level

Ответ 9

В первом фрагменте кода используется оператор приращения после операции, поэтому вызов выполняется как DoStuff (уровень);. Если вы хотите использовать здесь оператор приращения, используйте DoStuff (++ level);

Ответ 10

Уровень + 1 посылает любой уровень + 1 в функцию. level ++ отправляет уровень функции, а затем увеличивает его.

Вы можете сделать уровень ++, и это, скорее всего, даст вам нужные результаты.

Ответ 11

В первом примере используется значение "index", увеличивается значение и обновляется "индекс".

Второй пример использует значение "index" плюс 1, но не меняет содержание "индекса".

Итак, в зависимости от того, что вы хотите сделать здесь, могут быть сюрпризы!

Ответ 12

Пока возникает соблазн переписать как:

DoStuff(++level);

Я лично считаю, что это менее читаемо, чем приращение переменной до вызова метода. Как отмечено в приведенном выше параграфе, следующее было бы более ясным:

level++;
DoStuff(level);

Ответ 13

Когда вы используете язык, который позволяет перегрузку оператора, и '+ <integer> ' было определено для выполнения чего-то другого, кроме пост-и префикса '++'.

И снова я видел такие мерзости в школьных проектах *, если вы столкнулись с этим в дикой природе, у вас, вероятно, есть действительно хорошая, хорошо документированная причина.

[* стопка целых чисел, если я не ошибаюсь. "++" и "-" нажали и выскочили, а "+" и "-" выполнили нормальную арифметику]

Ответ 14

Чтобы выразить это самым простым способом, ++var является префиксным оператором и увеличит переменные до, остальная часть выражения будет оценена. var++, постфиксный оператор, увеличивает переменную после, остальная часть выражения оценивается. И, как говорили другие, конечно, var+1 создает только временную переменную (отдельную в памяти), которая инициируется с помощью var и увеличивается с константой 1.

Ответ 15

Насколько мне известно, выражение параметра сначала оценивается и получает значение уровня. Сама переменная увеличивается до того, как вызывается функция, потому что компилятор не заботится о том, используете ли вы это выражение в качестве параметра или иначе... Все, что он знает, это то, что он должен увеличивать значение и получать старое значение в результате выражение.

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