私の知る限り、キャッチされない例外の場合、C ++はローカル変数をすぐに破棄し、Javaは参照を解放し、残りをガベージコレクターに任せます。
これは正しいですか?この問題に関するJavaとC++の違いは正確には何ですか?言い換えると、スタックの巻き戻しの問題に関して、これら2つの言語のどちらが優れていると考えられますか?:)
私の知る限り、キャッチされない例外の場合、C ++はローカル変数をすぐに破棄し、Javaは参照を解放し、残りをガベージコレクターに任せます。
これは正しいですか?この問題に関するJavaとC++の違いは正確には何ですか?言い換えると、スタックの巻き戻しの問題に関して、これら2つの言語のどちらが優れていると考えられますか?:)
これで炎上するけど…
C++ は、スタックの巻き戻しの最前線で Java よりも確実に優れています。競合はありません。C++ オブジェクト デストラクタは、キャッチ ポイントに到達するまでスタックを逆方向に起動し、途中ですべてのマネージド リソースを適切に解放します。
あなたが言ったように、Javaはこれらすべてを非決定論的なガベージコレクターのなすがままにするか(最悪の場合)、明示的に作成された最終的にコードを散らかしたブロックの手に委ねます(Javaは真のRAIIをサポートしていないため) . つまり、すべてのリソース管理コードは、本来あるべきクラス デザイナーの手に委ねられるのではなく、各クラスのクライアントの手に委ねられます。
とはいえ、C++ では、デストラクタ自体が例外を発行しないように注意している場合にのみ、スタックの巻き戻しメカニズムが適切に機能します。アクティブな例外が 2 つあると、プログラムabort()
は go を渡しません (もちろん、残りのデストラクタは起動しません)。
スタックの巻き戻しは、完全に構築されたすべてのオブジェクトのデストラクタを、呼び出しチェーンを例外がキャッチされるポイントまで呼び出すことです。
Java には単純にスタックの巻き戻しがありません。例外がスローされた場合、オブジェクトに対して何もしません。ブロック内のオブジェクトを自分で処理する必要がcatch
あります。finally
これが主に、C# にusing
ステートメントが導入された理由です。ステートメントは IDisposable.Dispose() の呼び出しを簡素化しますが、C++ スタックの巻き戻しを完全に置き換えるものではありません。
スタックについては、両方とも同じことを行います。例外を残して残したブロックのスタックを解放します。Java では、すべてのプリミティブ型 (int、double など) が直接保存され、この型のローカル変数はこの時点で解放されます。すべてのオブジェクトは参照によってローカル変数に保存されるため、参照は削除されますが、オブジェクト自体はヒープに残ります。これがオブジェクトへの最後の参照であった場合、それらは次のガベージ コレクションで解放されます。C++ でヒープ上に作成されたオブジェクトがあり、ローカル変数がポインターを保持している場合、ヒープ上のオブジェクトは自動的に解放されず、ヒープ上に永久に残ります (はい、MEMORY LEAK が発生します)。オブジェクトをスタックに保存した場合は、デストラクタが呼び出されます (ヒープ上の他の参照オブジェクトを解放する場合があります)。
C++ は、スタック上の各関数を終了するときに、すべてのローカル変数を逆の順序で破棄します。プログラムで return を実行した場合と同じように、main()
.