1

昨日、ガベージコレクションについて話し合いました。

クラスを使用して作成されたオブジェクトはガベージコレクターによって収集されると説明されましたが、構造体を使用して作成されている場合、GCによって収集することはできません。

構造体はスタックを使用し、クラスはヒープを使用することを私は知っています。

しかし、GCが管理されていないコードだけを収集することは決してないと思います。つまり、Structureタイプはアンマネージコードであることを意味します。(私はそうは思わない)。

または、GCがスタックではなくヒープのみを処理するのですか?

はいの場合、intデータ型はどうですか。intはクラスではなく構造体です。したがって、int型のオブジェクトを定義した場合、それはGCによって管理されませんか?

4

4 に答える 4

6

GCルートからアクセスできない場合、 GCは管理対象オブジェクト(および構造体管理対象オブジェクト)を収集します。

ただし、structを使用して作成されている場合、GCで収集することはできません。

あなたが言われたことは間違っています。管理対象オブジェクトがどのように作成されたかは関係ありません。オブジェクトへの参照がなくなった場合、最終的に収集されます。

または、GCがスタックではなくヒープのみを処理することを意味しますか?

GCはオブジェクトグラフを処理します-オブジェクトがいずれかのGCルートから到達可能である場合、それらは収集されません。そうでない場合、オブジェクトは収集されることになります。スタックとヒープは関係ありません。

したがって、int型のオブジェクトを定義した場合、それはGCによって管理されませんか?

int(AKA System.Int32)は管理対象オブジェクト(構造)です。クラスでフィールドを宣言し、intそのクラスがスコープ外になったint場合、たとえば、はGCによって収集されることになります。


@leppie がコメントしたように、多くの場合、構造はスタックに配置され、スタックがポップされると、それらは存在しなくなります。このような場合、GCは関与しません(存在する必要はありません)。

于 2012-07-28T09:16:25.170 に答える
2

structを使用して作成されている場合、GCで収集することはできません。

違います。参照されていない場合は、最終的に収集されます。

構造体はスタックを使用し、クラスはヒープを使用することを私は知っています。

それはよくある誤解です。詳細については、このLippertの記事を参照してください

あなたが参照している考えは、プログラムの実行がスコープを離れるとすぐにスタックが破棄されるため、ほとんどの場合、 GCはスタックにあるデータの収集に煩わされないということだと思います。つまり、スタックに直接配置されたデータ(値型を意味し、他のすべてのデータへの参照を意味する必要があります)は自動的にクリアされ、GCを使用する必要はありません。GCの仕事は、(データ)タイプに関係なくヒープデータをクリアすることです。参照されていない場合は収集されます。

于 2012-07-28T09:23:34.657 に答える
1

しかし、GCが管理されていないコードだけを収集することは決してないと思います。つまり、Structureタイプはアンマネージコードです。(私はそうは思わない)。

あなたがここで何を求めているのかわかりません。

または、GCがスタックではなくヒープのみを処理することを意味しますか?

はい、いいえ。GCは、参照型のインスタンスに必要なメモリを処理します(常にマネージヒープで作成されます)。「スタック」は、現在の実行スレッドに関連付けられたメモリの一部として表示できます。スタックには、マネージヒープに割り当てられた参照型へのハンドルを含めることができます。この場合、GCは「気にかけます」:スタック上のこれらの参照が存在するまで、これらのインスタンスのマネージヒープからメモリを収集しません。スタックには、値型のインスタンス(!への参照ではない)を含めることもできます。その場合、GCは気にしません...

はいの場合、intデータ型はどうですか。intはクラスではなく構造体です。したがって、int型のオブジェクトを定義した場合、それはGCによって管理されませんか?

この質問は少し誤解を招きます。intスタック上ののインスタンスを「割り当てる」としましょう。

void Foo()
{
    // ...
    int tTmp;
    //...
}

この場合、GCはを気にしませんtTmp。スコープ外になると、現在のスレッドのスタックに配置され、削除されます。しかし、これを行う場合:

void Foo()
{
    //...
    var tTmp = new int [] {
        1, 2, 3, 4
    };
    //...
}

次に、4つの整数の配列がマネージヒープ上に作成され、GCが処理しtTmpます。また、配列の内容に必要なメモリを「間接的に」処理します。これは、たまたま4つの整数に必要なスペースです。

于 2012-07-28T09:53:57.543 に答える
0

.NET標準(ECMA-334)の内容をてみましょう

値型は、値型の変数がデータを直接含むという点で参照型とは異なりますが、参照型の変数はデータへの参照を格納します。後者はオブジェクトと呼ばれます。参照型を使用すると、2つの変数が同じオブジェクトを参照できるため、一方の変数に対する操作が、もう一方の変数によって参照されるオブジェクトに影響を与える可能性があります。値型では、変数はそれぞれ独自のデータのコピーを持っており、一方の操作が他方に影響を与えることはできません。

言い換えると、ガベージコレクターが値型を気にする理由はありません。値型は自分自身の後で(スコープ外になると)クリーンアップされるため、独自のデータが含まれているからです。GCは、共有(参照)データのクリーンアップ用です。

構造だけが値型ではないことに注意してください。

値型は、構造体型または列挙型のいずれかです。C#は、単純型と呼ばれる事前定義された構造体型のセットを提供します。単純なタイプは、予約語で識別されます。

たとえば、「int」型はいわゆる「単純型」、値型です。+-* /のような操作は、関数呼び出しではなく、プリミティブ操作にコンパイルされる可能性があるため、他の構造とは少し異なります。

于 2012-07-28T09:56:27.413 に答える