0

小さな配列を大きな配列に手動でコピーしています。

T is constrained to class, new()

これが GC をトリガーするのはなぜですか? 新しい配列への割り当ては参照によるものではありませんか? 古い配列の古い要素がまだガベージ コレクションされているのはなぜですか? 最初のループ内の割り当ては本当にそれらをコピーしますか?

public void Resize()
{
    T newArray = new T[oldArray.Length * 2];

    for (int i = 0; i < oldArray.Length; i++)
    {
        newArray[i] = oldArray[i];
    }

    for (int i = oldArray.Length; i < newArray.Length; i++)
    {
        // Assign new elements to the new array
    }

    oldArray = newArray;
}
4

1 に答える 1

3

呼び出すとすぐnewに、ヒープ上の新しいオブジェクトへの参照を作成します。参照を割り当てるとき

oldArray = newArray;

どちらの参照も新しいオブジェクトを指しています。指しているオブジェクトへの参照がなくなるoldArrayと、ガベージ コレクションの対象になります。

参考までに:

メモリを解放しています。ガベージ コレクターの最適化エンジンは、行われている割り当てに基づいて、コレクションを実行する最適な時間を決定します。ガベージ コレクターがコレクションを実行すると、アプリケーションで使用されなくなったオブジェクトのメモリが解放されます。アプリケーションのルートを調べて、使用されなくなったオブジェクトを特定します。すべてのアプリケーションには一連のルートがあります。各ルートは、マネージド ヒープ上のオブジェクトを参照するか、null に設定されます。アプリケーションのルートには、グローバル オブジェクト ポインターと静的オブジェクト ポインター、スレッドのスタック上のローカル変数と参照オブジェクト パラメーター、および CPU レジスタが含まれます。ガベージ コレクターは、ジャスト イン タイム (JIT) コンパイラとランタイムが保持するアクティブなルートのリストにアクセスできます。このリストを使用して、アプリケーションのルートを調べます。そしてその過程で、ルートから到達可能なすべてのオブジェクトを含むグラフを作成します。グラフにないオブジェクトは、アプリケーションのルートから到達できません。ガベージ コレクターは到達不能オブジェクトをガベージと見なし、それらに割り当てられたメモリを解放します。コレクション中に、ガベージ コレクターはマネージ ヒープを調べて、アクセスできないオブジェクトが占めているアドレス空間のブロックを探します。到達不能なオブジェクトをそれぞれ検出すると、メモリ コピー機能を使用してメモリ内の到達可能なオブジェクトを圧縮し、到達不能なオブジェクトに割り当てられたアドレス空間のブロックを解放します。到達可能なオブジェクトのメモリが圧縮されると、ガベージ コレクターは必要なポインターの修正を行い、アプリケーションのルートが新しい場所にあるオブジェクトを指すようにします。また、最後に到達可能なオブジェクトの後にマネージド ヒープのポインターを配置します。コレクションが大量の到達不能オブジェクトを検出した場合にのみ、メモリが圧縮されることに注意してください。マネージ ヒープ内のすべてのオブジェクトがコレクションに残っている場合、メモリの圧縮は必要ありません。パフォーマンスを向上させるために、ランタイムは別のヒープ内の大きなオブジェクトにメモリを割り当てます。ガベージ コレクタは、ラージ オブジェクトのメモリを自動的に解放します。ただし、メモリ内の大きなオブジェクトの移動を避けるために、このメモリは圧縮されません。ランタイムは、大きなオブジェクトのメモリを別のヒープに割り当てます。ガベージ コレクタは、ラージ オブジェクトのメモリを自動的に解放します。ただし、メモリ内の大きなオブジェクトの移動を避けるために、このメモリは圧縮されません。ランタイムは、大きなオブジェクトのメモリを別のヒープに割り当てます。ガベージ コレクタは、ラージ オブジェクトのメモリを自動的に解放します。ただし、メモリ内の大きなオブジェクトの移動を避けるために、このメモリは圧縮されません。

于 2013-04-28T17:33:30.893 に答える