2

私が次のものを持っていると考えてください:

edge some_edge;
std::priority_queue<edge> my_queue;

キューが空の場合でも、そのような「if」を書いても安全ですか?

if ((my_queue.size() > 0) && (my_queue.top().weight < some_edge.weight)) {
    do_something;
}

これはどうですか?

if ((my_queue.top().weight < some_edge.weight) && (my_queue.size() > 0)) {
    do_something;
}

左のオペランドが false と評価された場合、オペランド間の演算子が 'and' である式の評価は停止しますか?

4

5 に答える 5

4

C ++のステートメントは、左から右への結合演算子とif論理ブール演算子であり、短絡しているため、次のようなステートメントは、最初にサイズをチェックすることが保証されているため安全です(これらの演算子の悪意のあるオーバーロードがないと仮定)。&&||

if(myqueue.size() > 0 && myqueue.top().whatever) {
    // ...
}

ただし、キューをポップしたsize() 後にの戻り値を確認するため、この逆は当てはまりません。

余談ですが、私/多くの人が好む機能をstd::priority_queue提供しますが、それも機能します。empty()size() > 0

if(!myqueue.empty() && myqueue.top().whatever()) {
    // ...
}
于 2012-04-17T18:32:31.977 に答える
3

はい、この動作は C++ 標準に従って保証されています。

if (false && doSomething())

を評価することはありませんdoSomething()

ただし、 をオーバーロードするoperator&&と、すべての式が評価されるため、この動作が異なる可能性があります。これが、触れるのが悪い考えである理由operator&&です。

!empty()の代わりに使用する必要がsize() > 0あります。

于 2012-04-17T18:31:29.333 に答える
2

これは実際にはまったく問題ifではなく、約&&です。論理演算子 (&&との両方||) は、左側のオペランドを最初に評価します。次に、右側のオペランドが論理結果に影響を与える可能性がある場合にのみ、右側のオペランドを評価します。

&&場合、左のオペランドが に評価されるfalseと、結果はfalse右のオペランドの値に関係なく、右のオペランドは評価されません。

||場合、左のオペランドが に評価されるtrueと、結果はtrue右のオペランドの値に関係なく、右のオペランドは評価されません。

これは、 がステートメント&&の式に含まれているかどうかに関係なく当てはまります。if一部の難読化されたコードは、に変換してこれを利用if (x) y;x && yます。それほど頻繁には表示されませんが、同じことを行うこともでき||ます。

于 2012-04-17T18:36:35.317 に答える
1

このリンクは、&& には当てはまりますが、これがすべての演算子に当てはまるわけではないことを説明しています。特に、結合性と評価順序のコンテキストにおける左から右/右から左の違いに注意してください。http://en.cppreference.com/w/cpp/language/eval_order

于 2012-04-17T18:36:30.847 に答える
0

ブール式は短絡評価されるため、最初の部分が失敗した場合、2番目の部分は実行されません。したがって、最初の例は存在しないメモリにアクセスしませんが、2番目の例はアクセスします。

于 2012-04-17T18:32:26.327 に答える