4

一方、インターネットで読んでいると、静的変数は常に同じメモリアドレスを持っていることがわかりました。したがって、プログラムをコンパイルするときに、コンパイラは静的変数に割り当てるメモリアドレスを決定します。あなたがするときに何が起こるかについて私に考えさせた読書:

class Foo {}

class Program
{
    public static Foo someStaticVar;

    static void Main(string[] args)
    {
        Foo localVariable = new Foo();

        int x = 4;

        someStaticVar = localVariable; // is someStaticVariable still will have the same address?
    } 
    // variable x will be pushed of the stack
    // localVariable will be pushed of the stack
    // what happens then with someStatic var? 
}

また、メソッド内で変数を宣言すると、作成時にスタックにプッシュされ、メソッドが戻るときにスタックからポップアウトされることも学びました。それがすべて当てはまる場合、someStaticVarは消えるはずですが、消えません。

私は何かを間違って理解しなければならないと確信しています。あるいは、オンライン someStaticVar = localVariable;でそのオブジェクトのディープコピーを実行しているかもしれませんが、オブジェクトのディープコピーを実行する方法についてインターネット上に多くの質問があり、このアプローチとは大きく異なるため、私はそれを疑っています。

4

4 に答える 4

4

あなたが提供した例では、メソッドlocalVariableへのローカル変数のみです。MainMain メソッドの実行が終了すると、スコープ外になります。しかし、それを static フィールドに割り当てたので、作成された Foo インスタンスは引き続き Main メソッドの外に存在します。また、静的フィールドであるため、Program クラスの外でも有効です。

したがって、次のように段階的に行われます。

static void Main(string[] args)
{
    // an instance of Foo is created and pushed on the heap
    // localVariable is now pointing to the address of this instance
    // localVariable itself is stored on the stack
    Foo localVariable = new Foo();

    // someStaticVar is now pointing to the same location on the heap as
    // the localVariable - the Foo instance created earlier
    someStaticVar = localVariable; 
} 
// at this stage the Main method finishes executing and all local
// variables are falling out of scope. But since you have a static variable
// pointing to the Foo instance that was created inside the Main method this
// instance is not illegible for garbage collection because there are still 
// references to it (someStaticVar).

がインスタンス フィールドであり、静的ではない場合someStaticVar、同じプロセスが発生しますが、含まれているクラス (プログラム) への参照がなくなると、インスタンスはスコープから外れます。

于 2012-09-18T14:19:12.413 に答える
2

メソッド内で変数を宣言すると、作成時にスタックにプッシュされ、メソッドが戻るときにスタックからポップアウトされます。

Foo localVariable = new Foo();

ヒープに Foo オブジェクトを作成し、参照はスタックに保存されます。メソッドが完了すると、参照がスタックから削除されます。ガベージ コレクターは、Foo オブジェクトへの参照がないため、ヒープから Foo を削除するジョブを実行します。しかし、

someStaticVar = localVariable;

、 someStaticVar がヒープ上の Foo オブジェクトを参照するようになります。メソッドが終了した後でも、 someStaticVar は引き続き Foo オブジェクトを参照しています。そのため、ガベージ コレクターはその Foo オブジェクトを収集しません。 覚えておくべき主なことは、参照型のオブジェクトが作成されると、オブジェクトはヒープ上に作成され、参照はスタックに格納されることです。

質問は「静的フィールドはどこに格納されていますか?」、オブジェクトのインスタンスフィールドはヒープに格納され、ローカル変数はスタックに格納されますが、「静的変数はメモリ内のどこに存在しますか?

于 2012-09-18T14:26:38.493 に答える
1

オブジェクトのディープコピーはありません。オブジェクト自体はスタックではなくヒープに格納されます。あなたは正しいです、それsomeStaticVariableは常に同じアドレスを持っています。あなたの誤解は、そのアドレスに保存されているものにあると私は信じています。

object参照型(コードなどの任意の型)の変数を宣言する場合Foo、変数自体はオブジェクトではなく、オブジェクトのアドレスを格納する変数です。そのアドレスは単なる数字です。したがって、「のアドレス」はそれ自体someStaticVariableのアドレスではありません。FooアドレスのアドレスですFoo

同様に、これがあなたsomeStaticVarが「消えない」理由です。コードで発生するのは、aFooがメモリ内のあるアドレスで作成され、のメモリ内のアドレスlocalVariableを表す値に設定されることです。を実行すると、アドレスがからにコピーされるため、両方の変数が同じを指します。消えても影響を受けません。FoosomeStaticVar = localVariablelocalVariablesomeStaticVarFoolocalVariablesomeStaticVar

于 2012-09-18T14:23:31.667 に答える
1

この場合Fooはクラスなので、参照型です。型の変数は、実際には、オブジェクトが実際に格納されFooているメモリ内の場所へのポインターにすぎません。Foo

静的変数が一定のメモリアドレスを持っていると言うとき、そのメモリアドレスの値が一定であると言っているわけではありません。オブジェクトへのポインターのアドレスは変更されませんが、その固定メモリ位置に格納される数値 (この場合はアドレス) は、さまざまな潜在的なオブジェクト (または)Foo間で簡単に変わる可能性があります。Foonull

さらに、C# はマネージ言語でありアンマネージ言語ではないため、静的変数が一定のメモリ アドレスを持つとは言えません。確かに可能ですが、実際には依存すべきではない C# のメモリ マネージャーの実装の詳細です。

于 2012-09-18T14:25:41.207 に答える