web-dev-qa-db-ja.com

非短絡論理演算子が存在する理由

booleanオペランドとともに使用すると、&および|JLSのセクション15.22.2 ごとにlogical演算子になります。 。ただし、&&||とは異なり、これらは短絡しません。彼らは常に両側を評価します。ばかげた質問があります。より効率的な短絡論理演算子(&|)があるのに、なぜ効率の低い非短絡論理演算子(&&||)がまだ存在するのですか?つまり、短絡論理演算子とは対照的に、非短絡論理演算子の実際の使用法は何ですか?言い換えれば、非短絡論理演算子を使用して常に両側を評価することの使用法は何ですか?

36
namalfernandolk

更新された回答

お詫びします。あるのに、質問の「論理的」という言葉を見逃しました。 (私は編集でそれを少し強調する自由を取りました。)

左側の式がtrueまたはfalseのどちらを評価するかに関係なく、 always に副作用が発生する場合を考えてみます。例:コントラスト:

_if (foo() & bar()) {
    // Only call this if both operations returned true
}
_

_if (foo() && bar()) {
    // Only call this if both operations returned true
}
_

foobarの両方が、footrueまたはfalseを返すかどうかに関係なく、 want が発生する効果があると仮定しましょう。上記の最初のものでは、私はknowbarが常に呼び出され、その効果があることを知っています。後者では、もちろん、barが呼び出される場合と呼び出されない場合があります。非短絡バージョンがなかった場合は、一時変数を使用する必要があります。

_boolean fooResult, barResult;
fooResult = foo();
barResult = bar();
if (fooResult && barResult) {
    // ...
}
_

if (foo() & bar())を読み間違えるのは簡単すぎるので、とにかくを実行する必要があると主張するかもしれませんが(おそらくそうでしょう)、非短絡バージョンを持っています。

元の回答

_&_(または_|_)を短絡オペレーターにすることをどのように提案しますか? _&&_および_||_を使用すると、ブール条件を処理しているので意味があります。これらは真または偽であり、灰色の陰影はありません。ただし、_&_と_|_は、ブール値ではなくビットを処理します。結果は数字です。つまり、左側が_&_の場合、_0_は右側を評価できず、同様に、左側がすべての場合、_|_は右側を評価できなかったと思います。 -タイプが何であれビットオンですが、各演算子の1つのエッジケースを重要にすることにはあまり意味がありません(他の254以上のケースと比較して)。

29
T.J. Crowder

ブール式のコンポーネントに、すべての場合に実行したい操作が含まれる場合があります。パスワードの有効性をチェックする次の例を検討してください。

while ( !password.isValid() & (attempts++ < MAX_ATTEMPTS) ) {

    // re-Prompt

}

短絡のために2番目の条件が評価されなかった場合、attemptsは決してインクリメントされません。したがって、プログラマーの柔軟性が向上します。

14
paislee

私の場合(C++):

void setFields(Parameters bundle)
{
  if (setIfDifferent(&field1, bundle.value1) | 
      setIfDifferent(&field2, bundle.value2) |
      setIfDifferent(&field3, bundle.value3)) {
    storeState();
  }
}

setIfDifferent()は、オブジェクトのフィールドが異なる場合は新しい値で設定します。異なる場合はtrueを返します。または、フィールドと新しい値が同じ場合はfalseを返します。したがって、すべてのフィールドを設定して、いずれかが変更された場合は、新しいオブジェクトの状態を保存する必要があります。

2
Alex Che

論理式にはいくつかの副作用があります。たとえば、チェックと同時に割り当てることができます。 1つの部分だけが評価された場合、これは正しく機能しない可能性があります。

今は良い例を思い出せませんが、時々「非短絡」オペレーターが必要だったことを思い出してください。

うーん....以下は間違った例です。これは「非短絡」なしでは機能しません。または:

if( (object1=getInstance1()).getNumber() == 1 || (object2=getInstance2()).getNumber() == 2 ) {

    // do something which requires bot object1 and object2 assigned

}
1
Suzan Cioc

技術的に、&および|論理的ではなく、ブール値に関連付けられたときに論理演算子になるビット単位の演算子です。

論理式の中に代入式を含めたい場合があります。

いう:

if(a = (checkForSomeCondition()) | b = checkForAnotherCondition())
{
 //now do something here with a and b that has been cached
}

||を使用した場合、上記のチェックを実行できず、割り当てを個別のステートメントに分割する必要がありました。アプリケーションの開発中にこのようなシナリオに遭遇したことはありませんが、アルゴリズムの作成中に何度か遭遇します。

もちろん、論理式で単項演算子を使用したり、参照によって変数を述語に渡したりすることもできますが、これらは上記よりも一般的ではないようです。

0
arviman

私の場合、2つの異なるが関連するオブジェクト(Object2はObject1の属性)を比較して、変更があったかどうかを確認する2つのメソッドがあります。どちらかが更新された場合は更新を行う必要がありますが、両方が変更された場合にオブジェクトが変更されるように、両方を評価する必要があります。したがって、単一パイプの「OR」比較が必要です。

例:

if (compare(object1, currentObject1) | comparison(object2, currentObject2)) {
    updateObject1(object1);
}
0
Daniel Layher