1

新しいオブジェクトを作成することはできますが、それらを使い終わったときに、それらをすぐに破棄する方法も実際にはありませんか?

すべての OOP ランタイムがそのような動作を実装しなかったのはなぜですか?

開発者として、(多くの場合) オブジェクト インスタンスを使い終わったときに破棄するように構成できると確信しています。

function work(){
    var p1:Point = new Point(x, y);
    var p2:Point = new Point(x2, y2);

    ....

    destroy p1;
    destroy p2;
}
4

7 に答える 7

9

.NET から言えば、答えはメモリの安全性です。

2 つのアイテム A と B (オブジェクトまたはメソッド) がどちらもオブジェクト X への参照を保持していると
destroy X;ます。B には無効な参照が残されます。これは、アンマネージ言語でよく見られるエラー パターンです。手動破棄を削除すると、これを防ぐことができます。

しかし、同様に重要な問題は次のとおりです。答えはノーだ。短命のメモリは、.NET では非常に安価です。あなたが提案する破壊は何の価値もありません。

于 2010-09-18T18:57:11.033 に答える
5

簡単に言えば、それは一般的にプログラミング作業を複雑にするからです。手動のメモリ管理を正しく行うには、かなりのスキルと努力が必要です。その努力は、解決しようとしている実際のタスクには使用できません。

上記のシナリオは一般的ですが、唯一のシナリオではありません。オブジェクトの 1 つへの参照を返すとどうなるでしょうか。呼び出されたメソッド (格納される場所) への参照を渡すとどうなるでしょうか? などなど。これらはすべて、オブジェクトを責任を持って破棄する前に考慮する必要がある問題です。これらはまとめて「所有権」として知られています。

コインの反対側は、実行中に特定の時点でオブジェクトを破壊できることは本当にプラスの効果があるのでしょうか? これにより、非常に強力なイディオムである C++ のデストラクタと RAII が可能になります。Java にはそれがなく、私が Java を使い始めたとき、私はしばしばそれを見逃していました。ただし、Java でもこれらの問題を効果的に解決する方法があります (finallyブロックなど)。RAII がいかに洗練されていても、手動のメモリ管理によって引き起こされる可能性があるすべての混乱に見合うものではありません。

次に、「必要に応じてオブジェクトを明示的に破棄し、残りはガベージ コレクションであるという両方を実現できないのはなぜですか?」と提案するかもしれません。そして、コンパイラの作成者や JVM の実装者があなたを捕まえる前に、あなたはカバーのために走り始めることができます :-) それは問題を非常に複雑にするでしょう。手動のメモリ管理では、そのようなことはできません。

于 2010-09-18T18:58:19.873 に答える
2

いいえ、いいえ。Java/C# が C++ よりも優れている点の 1 つはメモリ管理です。自分で管理する必要がある場合はエラーが発生しやすくなり、人々がそれを使用して悪用する可能性があれば、ますます多くのエラーやメモリ リークが発生します。何かを解放するのを忘れるか、あまりにも早くそれを行うことによって。大規模なプロジェクトの設計/コーディングは、メモリ管理を考えずに行うのは非常に困難です。

于 2010-09-18T19:00:59.070 に答える
2

すべての OO 言語にガベージ コレクション (Java) または明示的なメモリ解放 (C++) があるわけではない理由は、各言語の設計で選択された戦略の結果です。Java では、プログラマがメモリを明示的に割り当てたり割り当て解除したりすることはできません。代わりに、プログラマは参照変数を処理するときに処理します

Point p = new Point(x,y);//p is a reference variable

p の割り当て解除は、ガベージ コレクションによって (自動的に) 行われます。ガベージ コレクションを行うには、明示的なシンボリック参照を選択し、ポインターを使用しません。その結果、C++ にはガベージ コレクションがなく、言語固有の機能として提供することはできません。プログラマーは、以下を使用してメモリの割り当てを明示的に解除する必要があります。

delete p;

または、ガベージ コレクションの独自の実装を記述します。したがって、OO 言語の設計に応じて、ガベージ コレクションまたは手動の割り当て解除のいずれかが行われます。両方を持つことはできません。

于 2010-09-18T19:46:46.110 に答える
1

ほとんどの言語では、既存の参照を null または同様のものに設定できます。これにより、必要に応じてランタイムがガベージ コレクションを実行できるようになります。

システムにメモリを管理させるという利便性のために支払う代償は、必要なときに自分でメモリを管理する能力の多くを失うことだと思います

于 2010-09-19T10:23:10.533 に答える
1

C++ は OOP 言語です。また、オブジェクトの構築に使用できる「new」キーワードと、オブジェクトの破棄に使用できる「delete」キーワードを提供します。注意して使用しないと、delete オブジェクトは C++ で悲惨な結果をもたらす可能性があります。1 つのオブジェクトにそれを参照する 2 つのポインターがあり、そのオブジェクトを一方のポインターから削除すると、もう一方のポインターは無効になり、それを使用しようとすると未定義の動作になります (通常、プログラムはメモリ位置の値を使用しようとします)。 ; ランタイムによって他の目的のためにすでに再割り当てされている可能性があります)

于 2010-09-18T19:12:51.000 に答える
1

Java については、Runtime.gc()を参照してください。

C# については、System.GC.Collect を参照してください。

C# については完全にはわかりませんが、Java ではガベージ コレクションの実行を要求することしかできませんが、未使用の参照を実際にクリーンアップするかどうかの決定は仮想マシンに任されています。

C++ スタイルのメモリ管理とインタープリター言語でのガベージ コレクションのどちらがパフォーマンスが優れているかについては多くの議論がありますが、Java や C# の作業を行っている場合、本当にガベージ コレクションを強制する必要があるかどうか、一般的にはC++ から来ている場合は、メモリを管理したいという誘惑に抵抗し、VM の最適化に任せることをお勧めします。ガベージ コレクションできるように、使用していないオブジェクトへのすべての参照を解放したことを確認する必要があります。私はいつでも心配しません。

于 2010-09-18T19:28:59.640 に答える