为什么c ++没有&& =或|| =为布尔?

时间:2010-03-21 19:29:40

标签: c++ boolean-operations

是否有"very bad thing"可以发生&& =和|| =被用作bool foo = foo && barbool foo = foo || bar的语法糖?

3 个答案:

答案 0 :(得分:65)

{+ 1}}在C ++中可能只有booltrue。因此,使用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)