Короткий ответ
Все операторы +=
, -=
, *=
, /=
, &=
, |=
... являются арифметическими и обеспечивают такое же ожидание:
x &= foo() // We expect foo() be called whatever the value of x
Однако операторы &&=
и ||=
будут логичными, и эти операторы могут быть подвержены ошибкам, потому что многие разработчики ожидают, что они foo()
будут всегда вызваны x &&= foo()
.
bool x;
// ...
x &&= foo(); // Many developers might be confused
x = x && foo(); // Still confusing but correct
x = x ? foo() : x; // Understandable
x = x ? foo() : false; // Understandable
if (x) x = foo(); // Obvious
Неужели нам действительно нужно сделать C / C ++ еще более сложным, чтобы получить ярлык x = x && foo()
?
Неужели мы действительно хотим еще больше запутать загадочное утверждение x = x && foo()
?
Или мы хотим написать осмысленный код вроде if (x) x = foo();
?
Длинный ответ
Пример для &&=
Если &&=
оператор был доступен, то этот код:
bool ok = true; //becomes false when at least a function returns false
ok &&= f1();
ok &&= f2(); //we may expect f2() is called whatever the f1() returned value
эквивалентно:
bool ok = true;
if (ok) ok = f1();
if (ok) ok = f2(); //f2() is called only when f1() returns true
Этот первый код подвержен ошибкам, потому что многие разработчики думают, что f2()
он всегда вызывается независимо от f1()
возвращаемого значения. Это похоже на запись, bool ok = f1() && f2();
где f2()
вызывается, только когда f1()
возвращается true
.
- Если разработчик действительно хочет,
f2()
чтобы его вызывали только при f1()
возврате true
, следовательно, второй код выше менее подвержен ошибкам.
- Иначе (разработчик хочет,
f2()
чтобы его всегда вызывали) &=
достаточно:
Пример для &=
bool ok = true;
ok &= f1();
ok &= f2(); //f2() always called whatever the f1() returned value
Более того, компилятору проще оптимизировать этот код выше, чем код ниже:
bool ok = true;
if (!f1()) ok = false;
if (!f2()) ok = false; //f2() always called
Сравните &&
и&
Мы можем задаться вопросом, дают ли операторы &&
и &
тот же результат при применении к bool
значениям?
Давайте проверим, используя следующий код C ++:
#include <iostream>
void test (int testnumber, bool a, bool b)
{
std::cout << testnumber <<") a="<< a <<" and b="<< b <<"\n"
"a && b = "<< (a && b) <<"\n"
"a & b = "<< (a & b) <<"\n"
"======================" "\n";
}
int main ()
{
test (1, true, true);
test (2, true, false);
test (3, false, false);
test (4, false, true);
}
Вывод:
1) a=1 and b=1
a && b = 1
a & b = 1
======================
2) a=1 and b=0
a && b = 0
a & b = 0
======================
3) a=0 and b=0
a && b = 0
a & b = 0
======================
4) a=0 and b=1
a && b = 0
a & b = 0
======================
Вывод
Поэтому YES мы можем заменить &&
на &
для bool
значений ;-)
Так что лучше использовать &=
вместо &&=
.
Мы можем считать &&=
бесполезным для логических значений.
То же самое для ||=
оператор |=
также менее подвержен ошибкам, чем||=
Если разработчик хочет, чтобы f2()
его вызывали только при f1()
возврате false
, а не:
bool ok = false;
ok ||= f1();
ok ||= f2(); //f2() is called only when f1() returns false
ok ||= f3(); //f3() is called only when f1() or f2() return false
ok ||= f4(); //f4() is called only when ...
Я советую следующую более понятную альтернативу:
bool ok = false;
if (!ok) ok = f1();
if (!ok) ok = f2();
if (!ok) ok = f3();
if (!ok) ok = f4();
// no comment required here (code is enough understandable)
или, если вы предпочитаете стиль единой линии :
// this comment is required to explain to developers that
// f2() is called only when f1() returns false, and so on...
bool ok = f1() || f2() || f3() || f4();