是否有"very bad thing"可以发生&& =和|| =被用作bool foo = foo && bar
和bool foo = foo || bar
的语法糖?
答案 0 :(得分:65)
{+ 1}}在C ++中可能只有bool
或true
。因此,使用false
和&=
是相对安全的(尽管我并不特别喜欢这种表示法)。确实,它们将执行位操作而不是逻辑操作(因此它们不会短路)但这些位操作遵循定义良好的映射,这实际上等同于逻辑操作 as 两个操作数的类型为|=
。 1
与其他人在此处所说的相反,C ++中的bool
必须永远不会有bool
等不同的值。将该值分配给2
时,它将按照标准转换为bool
。
将无效值转换为true
的唯一方法是在指针上使用bool
:
reinterpret_cast
但是,由于此代码导致未定义的行为,我们可以安全地忽略符合C ++代码的这个潜在问题。
1 无可否认,这是一个相当大的警告,因为Angew的评论说明:
int i = 2;
bool b = *reinterpret_cast<bool*>(&i);
b |= true; // MAY yield 3 (but doesn’t on my PC!)
原因是bool b = true;
b &= 2; // yields `false`.
执行整数提升,使得表达式等同于b & 2
,从而产生static_cast<int>(b) & 2
,然后将其转换回0
。因此,bool
的存在确实可以提高类型安全性。
答案 1 :(得分:42)
&&
和&
具有不同的语义:如果第一个操作数为&&
,则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();
答案 2 :(得分:22)
所有运营商+=
,-=
,*=
,/=
,&=
,|=
...都是算术运算并提供相同的期望:
x &= foo() // We expect foo() be called whatever the value of x
但是,运算符&&=
和||=
是合乎逻辑的,并且这些运算符可能容易出错,因为许多开发人员都希望foo()
始终调用x &&= foo()
。< / p>
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
======================
因此是我们可以&&
替换&
bool
值;-)
因此,最好使用&=
代替&&=
。
我们可以认为&&=
对布尔人来说毫无用处。
||=
运营商
|=
的容易出错 <{1}}
如果开发人员希望仅在||=
返回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)