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

问题描述 投票:104回答:3

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

c++ boolean-operations
3个回答
68
投票

bool可能只提供C ++ truefalse。因此,使用&=|=是相对安全的(即使我特别不喜欢的符号)。诚然,他们将执行位操作,而不是逻辑操作(并且因此它们不会短路),但这些位操作遵循良好定义的映射,这是有效地等同于逻辑操作,只要这两个操作数的类型的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 &&=的存在会提高类型安全。


43
投票

&&&有不同的语义:如果第一个操作&& 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();

24
投票

Short answer

所有运营商+=-=*=/=&=|= ......是算术,并提供同样的期望:

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();有意义的代码?

Long answer

例如用于&&=

如果&&=操作者可用,那么这段代码:

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();
© www.soinside.com 2019 - 2024. All rights reserved.