C ++にブール値の&& =または|| =がないのはなぜですか?


126

そこにある「非常に悪いもの」が起こる可能&&=||=のためのシンタックスシュガーとして使用されたbool foo = foo && barとはbool foo = foo || bar


5
この他の質問を参照してくださいstackoverflow.com/questions/2324549/... 1件のJavaについてだが、C系統を共有し、同じ引数のほとんどが適用されることを。
jamesdlin 2010年

基本的に、c ++にはそれが含まれていません。Rubyのような言語には含まれていません。boo ...
Kache

2
しかし、Ruby x ||= yではx = x ? x : y;、どのタイプでもC ++ とほぼ同等ではありませんか?つまり、「まだ設定されていない場合はyに設定してください」。これは、CやC ++よりもはるかに便利ですx ||= y。(演算子のオーバーロードを禁止する)は、「(bool)yまだ設定されていない限り、xを設定」します。そのために別の演算子を追加することは心配していません。少し微妙に思えます。書くだけif (!x) x = (bool)y。しかし、boolその場合、その1つの型でのみ非常に役立つ追加の演算子が必要になるほど、変数を実際には使用しません。
スティーブジェソップ

1
C ++が持っていない、&&=または||=Cが持っていない主な理由は確かです。Cがそれらを持たない理由は、機能性が十分に有益であるとは考えられなかったためだと私は合理的に確信しています。
Jonathan Leffler、2015

2
また、は評価の前に初期化されていないbool foo = foo || bar;ため、表記法は非常にわかりやすいため、未定義の動作を呼び出します。もちろん、これは次のようなものであることを意図しており、質問は有効です。foofoo || barbool foo = …initialization…; …; foo = foo || bar;
Jonathan Leffler、2015

回答:


73

A boolはC ++でのみ、trueまたはfalseC ++でのみ使用できます。そのため、&=and を使用すること|=は比較的安全です(ただし、表記法は特に好きではありませんが)。確かに、これらは論理演算ではなくビット演算を実行します(したがって、これらは短絡しません)が、これらのビット演算は明確に定義されたマッピングに従います。これは両方のオペランドが型である限りbool、論理演算と実質的に同等です。1

他の人がここで言ったこととは逆にbool、C ++のは、などの別の値を持つことはできません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 &&=型の安全性を向上させることは事実です。


4
しかし&&と|| 演算子は、boolだけでなく、boolに変換されるものであれば何でも処理します。
dan04 2010年

13
boolであっても、同じことはしません。||そして&&ショートカットは、すなわち第二引数ではありませんオペランド最初のオペランドがある場合true(それぞれfalseのため&&)。|&|=&=常に両方のオペランドを評価します。
Niki

4
これは、なぜ&& =と|| =がC ++演算子ではないのかという質問には答えません。
2015年

9
typeの左側に使用するの安全ではありません。右側がそれ以外のタイプ(または真の値に対してゼロ以外を返す別のC stdlib関数など)になる可能性があるためです。仮説があった場合、おそらく右側を強制的にに変換しますが、変換しません。つまり、結果はになります。&=boolboolislower&&=bool&=bool b = true; b &= 2;b == false
Angewは、2016

2
@Antonioタフな群衆。😝–
Konrad Rudolph

44

&&&セマンティクスが異なる:&&最初のオペランドがの場合、2番目のオペランドは評価されませんfalse。すなわちのようなもの

flag = (ptr != NULL) && (ptr->member > 3);

安全ですが

flag = (ptr != NULL) & (ptr->member > 3);

そうではありませんが、両方のオペランドのタイプはboolです。

&=and についても同じことが言えます|=

flag = CheckFileExists();
flag = flag && CheckFileReadable();
flag = flag && CheckFileContents();

以下とは異なる動作をします:

flag = CheckFileExists();
flag &= CheckFileReadable();
flag &= CheckFileContents();

35
私の意見では&& =を使う理由はなおさらです。= P
Kache

4
しかし、これは実際には答えではありません。
Catskul

27

短い答え

すべての演算子は+=-=*=/=&=|=...算術演算であり、同じ期待を提供します。

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

  • 開発者がreturnのf2()ときだけ呼び出されるようにしたい場合f1()true、上記の2番目のコードの方がエラーが発生しにくくなります。
  • 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値;-)
だから、より良い使用&=するのではなく&&=。ブール値には役に立たない
と考えることができ&&=ます。

同じ ||=

オペレータは|=また、小さいエラーを起こしやすいより||=

開発者がreturnの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)

または、すべてを1つのラインスタイルで使用する場合:

// 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();

13
実際にこの動作が必要な場合はどうなりますか?左側の式が間違っている場合、右側の式は実行されません。変数を2回書き込むのは面倒です。たとえば、success = success && DoImportantStuff()
Niklas R

1
私のアドバイスは、書くことif(success) success = DoImportantStuff()です。ステートメントsuccess &&= DoImportantStuff()が許可された場合、多くの開発者はDoImportantStuff()、の値が何であれ常に呼び出されると考えますsuccess。これがあなたの疑問に答えることを願っています...私も私の答えの多くの部分を改善しました。私の答えが理解しやすくなったか教えてください。(コメントの目的について)乾杯、またね;-)
olibre 2013

9
「この発言success &&= DoImportantStuff()が許可された場合、多くの開発者はDoImportantStuff()、成功の価値が何であれ、常に呼ばれると考えるでしょう。あなたはそれについて言うことができif (success && DoImportantStuff())ます。彼らがif構文の背後にあるロジックを覚えている限り、問題はありません&&=
ピルチ2014年

2
f1()常にで評価されると人々がどのように想定するかはわかりませんが、常にで評価されるok &&= f(1) とは想定していませんok = ok && f(1)。私と同じように思われます。
アインポクルム2016

1
私は実際にv1 += e2v1 = v1 + e1、変数v1と式e2の同等の構文糖になると期待 しています。ただの省略表記、それだけです。
einpoklum 2016
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.