Как работает x = x++ и x = ++x?
Пусть x = 5. Тогда в обоих случаях cout << x даст 6. Но в случае x = x++, кажется, что работать должно так:
- Отрабатывает x++: заведется переменная y, куда положится 5. Затем x увеличится на 1. Итого возвращается значение 5, а x = 6.
- Отрабатывает присваивание: переменной x=6 присваивается значение 5. Подскажите, пожалуйста, где ошибка в понимании работы?
Ответы (3 шт):
++X; //Префикс
X++; //Постфикс
Префикс увеличивает значение, а затем высчитывает выражение. Постфикс высчитывает выражение, а затем осуществляет увеличение.
x = 5;
y = ++x //Получится 6
z = x++ //присваевает значение x к z, а затем производит его вычесление. получится 6, так как z присвоил значение x, а потом увеличил его на единицу.
До C++17 оба варианта вызывают неопределенное поведение, см. order of evaluation.
Начиная с C++17, насколько я понял, x = x++ не меняет значение x, а x = ++x увеличивает его на 1.
Объяснение в вопросе правильное. Если ваш компилятор дает другой результат, то или он не поддерживает C++17, или в нем баг.
Последние GCC и Clang выдают правильный результат, хотя почему-то с предупреждениями.
Рассмотрим первый пример x = ++x;
Сначала будет посчитано значение справа от знака присваивания, а затем будет выполнено само присваивание.
1) Выполнение преинкремента. Значение x увеличивается на единицу и возвращается новое значение x-а.
2) Выполняется оператор присваивания.
т.е можно расписать вот так:
x = x + 1; (преинкремент)
x = x; (присваивание)
Если изначально x равнялся 5, то его значение, после этих операций, будет 6
Второй пример x = x++;
1) Выполнение постинкремента. Говорят, что сначала возвращается значение x, а потом увеличение x-а на 1. На самом деле снимается копия с переменной x, происходит инкремент, возвращение старого значения x (копии)
2) Выполняется оператор присваивания.
т.е можно расписать вот так:
auto y = x;
x = x + 1; (постинкремент)
x = y; (операция вернула y (копию старого значения x))
Т.е если в начале x = 5, то операция постинкремента вернет 5 (хотя значение x-а в этот момент равно 6-ти), а затем вызовется оператор присваивания и x (в котором все еще лежит 6) затерется результатом операции постинкремента (ну т.е. 5)
В результате во втором примере в x лежит 5