Предположим, фрагмент кода
bool a;
a = true;
a |= mayRun();
a = false;
a |= mayRun();
в каком случае выполняется mayRun ()?
Все объяснения говорят мне, что
a |= b;
эквивалентно
a = a | b;
Но это не может быть таким же, как пример
arr[i++] |= b;
указывает на то.
Это всегда выполняется. Обратите внимание, что a |= b
это действительно сокращение для a = a | b
(только оценка a
один раз). В частности, это не сокращение для a = a || b
,
Это означает, что он не обеспечивает короткого замыкания логических операторов, поэтому b
всегда оценивается.
Используя эти сокращенные формы назначения с bool
переменные опасны именно потому, что семантика неочевидна. &=
на самом деле еще хуже. Сравните это:
int two() { return 2; }
int main()
{
bool b = true;
b = b && two();
assert(b); //OK
}
с этим:
int two() { return 2; }
int main()
{
bool b = true;
b &= two();
assert(b); //FAILS!!
// b &= two(); was actually b = 1 & 2, which is 0 !
}
Короче говоря, избегайте использования |=
а также &=
с логическими переменными.
Он всегда будет выполняться, потому что короткое замыкание не применимо к побитовым операциям (применимо только к логическим операциям, таким как &&
а также ||
).
Обратите внимание, что это неправильное представление может привести к неприятным ошибкам — разработчик предположит, что существует короткое замыкание, но его нет, и все части выражения выполняются всегда, и это изменяет логику программы.
в каком случае
mayRun()
выполняется?
Это всегда будет выполнено.
Возможно, вы ожидали |=
выполнить короткое замыкание, но это не так: это происходит только с логический операторы &&
а также ||
, когда результат может быть определен только из первого операнда. Там нет логических составных операторов присваивания, таких как ||=
, поэтому короткое замыкание никогда не произойдет в выражении присваивания.
Все объяснения говорят мне, что
a |= b;
эквивалентноa = a | b;
Почти; но все объяснения, которые вы читали, упустили важную деталь.
Но это не может быть таким же, как пример
arr[i++] |= b;
указывает на то.
Действительно, есть разница, как указано в C ++ 11 5.17 / 7:
Поведение выражения формы
E1 op = E2
эквивалентноE1 = E1 op E2
за исключением того, что E1 оценивается только один раз.