if
Standardは、条件式の評価中に構築された一時オブジェクトの存続期間をどのように定義しますか?
私はこの情報を探して、10ページの$ 1.9の[10]を指す例で似たようなものを見つけました(ここでは新しい仕様の最終ドラフトを参照しています)。 Visual C ++の動作は、その例の理解とは異なるため、質問することにしました。
仕様への適切な参照を提供してください。
オブジェクトに名前を付けると、オブジェクトは全体にわたって持続します(つまり、ブロックとブロックif
の両方ですが、終了する前に破棄されます)。true
false
if
例えば:
if ( MyClass x = f() ) { /* ... */ } else { /* ... */ }
nextInstruction();
x
両方のブロックで使用できますが、呼び出されるif
前に破棄されます。nextInstruction
しかし、名前を付けないとどうなりますか?
if ( f() ) { /* ... */ } else { /* ... */ }
nextInstruction();
仕様の参照部分についての私の理解では、によって返される値は、実行がブロックの1つ(forまたはfor )f()
に入る前に破棄されます。true
false
ただし、Visual C ++は、その一時オブジェクトを名前が付けられているかのように破棄します。(編集: Tino Didriksenが指摘したように、ここではVisual C ++がうまく機能します。実際、今でもそれを確認しています。最初のテスト結果を見るときに間違いを犯したに違いありません!)
これは、一部のエッジケースでは重要です(ここでは、それらがどの程度発生する可能性があるか、またはそのようにコードを記述することが適切かどうかについては説明しません...)。
たとえば、次のようにします。
class ScopedLock {
public:
~ScopedLock() { if ( isLocked() ) unlock(); }
operator bool() const { return isLocked(); }
/* ... */
};
次のようなコードがある場合:
if ( ScopedLock lock = resource.lock() ) { /* ... */ }
実行がtrue
ブロックに入るとき、私たちはリソースを所有し、そのブロックを離れる前にリソースのロックが解除されないことを確認できます。
しかし、誰かが次のように書いた場合はどうなりますか?
if ( resource.lock() ) { /* ... */ }
ここで、一時的なデストラクタScopedLock
が呼び出されることが重要です。これは、このコードが正しいかどうかを判断するためです(リソース使用量の意味で)。(ここでも、そのようなコードを書くことが一般的に悪いかどうかについての議論をスキップしましょう。それはこの質問のポイントではありません...)