是否有可能发生一个"very bad thing" && =和|| =被用作bool foo = foo && bar
和bool foo = foo || bar
语法糖?
甲bool
可能只提供C ++ true
或false
。因此,使用&=
和|=
是相对安全的(即使我特别不喜欢的符号)。诚然,他们将执行位操作,而不是逻辑操作(并且因此它们不会短路),但这些位操作遵循良好定义的映射,这是有效地等同于逻辑操作,只要这两个操作数的类型的bool
.1
相反的是其他人在此间表示,在C ++中bool
绝不能有不同的值,如2
。当指定该值到bool
,它会被转换为true
按照标准。
得到一个无效值成bool
的唯一方法是通过使用reinterpret_cast
指针上:
int i = 2;
bool b = *reinterpret_cast<bool*>(&i);
b |= true; // MAY yield 3 (but doesn’t on my PC!)
但由于未定义行为这个代码的结果,无论如何,我们可以安全地忽略符合C ++代码这个潜在的问题。
1诚然,这是一个相当大的警告作为Angew的评论说明:
bool b = true;
b &= 2; // yields `false`.
其原因是,b & 2
执行整数提升,使得表达式然后相当于static_cast<int>(b) & 2
,这导致0
,然后将其转换回bool
。所以,这是真的,一个operator &&=
的存在会提高类型安全。
&&
和&
有不同的语义:如果第一个操作&&
false
不会计算第二个操作数。即像
flag = (ptr != NULL) && (ptr->member > 3);
是安全的,但
flag = (ptr != NULL) & (ptr->member > 3);
不是,虽然两者操作数的类型bool
的。
这同样适用于&=
和|=
真:
flag = CheckFileExists();
flag = flag && CheckFileReadable();
flag = flag && CheckFileContents();
将具有不同的行为:
flag = CheckFileExists();
flag &= CheckFileReadable();
flag &= CheckFileContents();
所有运营商+=
,-=
,*=
,/=
,&=
,|=
......是算术,并提供同样的期望:
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
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
======================
所以是的,我们能为&&
值由&
更换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();