Я искал и нашел формулу: a = (a + b) - (b = a)
предполагается, что в некоторых случаях они заменяют две переменные (или объекты). Однако я тестировал его с помощью C ++ и php, это дало мне другой результат.
PHP:
$a = 10; $b = 20; $a = ($a + $b) - ($b = $a); echo $a, " ", $b;
Это печатает 20 10
C ++
int a = 10; int b = 20; a = (a + b) - (b = a); std::cout << a << " " << b;
Это печатает 10 10
Код выглядит одинаково, но результаты разные, я думал о двух причинах:
Может ли кто-нибудь объяснить, почему C ++ и php-выход отличаются в этой ситуации?
Я не уверен, что такое правила в PHP, но на C ++ порядок отдельных подвыражений строго не определен или, как технический термин, «неуказан» – другими словами, компилятор разрешен для вычисления b = a
до или после него a + b
. Пока он делает a + b
и b = a
перед вычитанием. Использование «неуказанного» поведения позволяет компилятору создавать более эффективный код в некоторых случаях или просто создавать компилятор для некоторых архитектур.
Это также означает, что если у вас есть выражение, которое «пересчитывает» значение внутри самого выражения, а также использует его в другом месте выражения, вы получаете неопределенное поведение (короткое замыкание в UB). UB означает именно это, поведение не определено – почти все может случиться, в том числе то, что вы видите, и многие другие альтернативы (например, компилятору также разрешено производить 42, даже если логика говорит, что ответ не будет 42 в этом случае [это неправильный вопрос для этого!]).
Я бы также предположил, что если вы захотите обменять два значения, в PHP:
$t = $a; $a = $b; $b = $t;
и в C ++:
#include <algorithm> std::swap(a, b);
или если вы настаиваете на написании своих собственных:
int t = a; a = b; b = t;
Попытка быть умной и выполнять ее «без временной переменной» почти наверняка сделает ее медленнее, чем использование временного – конечно, на компилируемом языке, таком как C ++, – на интерпретируемом языке, таком как PHP, создание новой переменной может добавить немного дополнительных накладных расходов, но это вряд ли будет таким большим, по сравнению с дополнительными усилиями в требуемой логике.
Код C ++ полностью разрушен из-за неопределенного поведения. (чтение и запись b
в одной точке последовательности).
Для PHP:
$a = 10; $b = 20; $a = ($a + $b) - ($b = $a); //executes like thus $a = (30) - ($b = $a); $a = (30) - ($b = $a = 10); //new $a still not computed, using older $a $a = (30) - (10); $a = 20; //then, $a=20 and $b = 10
Это полностью связано с приоритетом оператора , это может быть одинаковым на C или не может, это зависит от приоритета, если непредвиденное поведение не происходит.