简体   繁体   English

将方法内的局部变量的引用分配给公共静态变量时会发生什么

[英]What happens when you assign reference of local variable inside method to public static variable

Meanwhile reading on the internet I learned that static variables always have the same memory address. 同时在互联网上阅读我了解到静态变量总是具有相同的内存地址。 So when compiling the program, the compiler is going to decide what memory address to assign to the static variables. 因此,在编译程序时,编译器将决定分配给静态变量的内存地址。 Reading that made me think about what happens when you do: 阅读让我思考你做什么时会发生什么:

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? 
}

I also learned that when declaring variables inside a method they will be pushed to the stack when created and popped out the stack when the method returns. 我还了解到,当在方法中声明变量时,它们将在创建时被推送到堆栈,并在方法返回时弹出堆栈。 If all that is true then someStaticVar should disappear but it doesn't. 如果一切都是真的那么someStaticVar应该消失,但事实并非如此。

I am sure I must understood something incorrectly. 我相信我必须理解错误的东西。 Or maybe on the line someStaticVar = localVariable; 或者也许就行someStaticVar = localVariable; is performing a deep copy of that object but I doubt it because there are a lot of questions on the interenet on how to do a deep copy of an object and they are much different than this approach. 正在执行该对象的深层复制,但我对此表示怀疑,因为在interenet上有很多关于如何对对象进行深层复制的问题,并且它们与此方法有很大不同。

In the example you provided localVariable is only a local variable to the Main method. 在您提供的示例中, localVariable只是Main方法的局部变量。 It falls out of scope once the Main method ends executing. 一旦Main方法结束执行,它就会超出范围。 But since you have assigned it to the static field, the Foo instance that was created will continue to live outside of the Main method. 但由于您已将其分配给静态字段,因此创建的Foo实例将继续存在于Main方法之外。 And since it is static field it will live even outside of the Program class. 而且由于它是静态字段,它甚至可以在Program类之外生存。

So here's what happens step by step: 所以这是一步一步发生的事情:

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).

If someStaticVar was an instance field and not static then the same process will happen except that the instance will fall out of scope once there are no longer any references to the containing class (Program). 如果someStaticVar是一个实例字段而不是静态字段,则会发生相同的过程,除非一旦不再引用包含类(Program),实例将超出范围。

when declaring variables inside a method they will be pushed to the stack when created and popped out the stack when the method returns. 当在方法中声明变量时,它们将在创建时被推送到堆栈,并在方法返回时弹出堆栈。

Foo localVariable = new Foo(); Foo localVariable = new Foo();

will create Foo object on heap, & reference is stored on stack. 将在堆上创建Foo对象,并将引用存储在堆栈上。 when method completes, references is removed from stack. 当方法完成时,将从堆栈中删除引用。 Garbage collector will do job of removing Foo from heap as there will be no reference to Foo object. 垃圾收集器将从堆中删除Foo,因为不会引用Foo对象。 But, 但,

someStaticVar = localVariable; someStaticVar = localVariable;

, will cause, someStaticVar to reference Foo object on heap. ,会导致someStaticVar在堆上引用Foo对象。 Even after method exits, someStaticVar will still be refering Foo object. 即使在方法退出后,someStaticVar仍然会引用Foo对象。 so, garbage collector wont collect that Foo object. 所以,垃圾收集器不会收集那个Foo对象。 Main thing to remember is , when Reference type's object is created, object is created on heap, & reference is stored on stack. 要记住的主要事情是,当创建引用类型的对象时,在堆上创建对象,并将引用存储在堆栈上。

Questions is "where static field is stored?", object's instance fields are stored on heap, local variables are stored on stacks, but where "static variable exist in memory? " 问题是“静态字段存储在哪里?”,对象的实例字段存储在堆上,局部变量存储在堆栈上,但“静态变量存在于内存中?

There is no deep copying of the object: the object itself is stored on the heap, not on the stack. 没有深度复制对象:对象本身存储在堆上,而不是堆栈上。 You are correct that someStaticVariable will always have the same address. 你是正确的someStaticVariable将始终具有相同的地址。 Your misunderstanding, I believe, is in what's stored at that address. 我相信你的误解就是在那个地址存储的内容

When you declare a variable of a reference type (any object type, such as Foo in your code), the variable itself isn't the object: it's a variable that stores the address of your object. 当您声明引用类型的变量(任何object类型,例如代码中的Foo )时,变量本身不是对象:它是存储对象地址的变量。 That address is just a number. 那个地址只是一个数字。 So, "the address of someStaticVariable " isn't the address of the Foo itself; 所以,“ someStaticVariable的地址”不是Foo本身的地址; it's the address of the address of the Foo . 它是Foo 地址的地址

In the same way, this is why your someStaticVar doesn't "disappear." 以同样的方式,这就是你的someStaticVar不会“消失”的原因。 What happens in your code is that a Foo is created at some address in memory, and localVariable is set to a value that represents the address in memory of the Foo . 你的代码中发生的事情是在内存中的某个地址创建了Foo ,而localVariable设置为表示Foo 内存中的地址的值。 When you perform someStaticVar = localVariable , what happens is that the address is copied from localVariable to someStaticVar , and thus both variables point at the same Foo . 当您执行someStaticVar = localVariable ,什么情况是,该地址被复制从localVariablesomeStaticVar ,因而这两个变量指向同一Foo When localVariable disappears, someStaticVar is not affected. localVariable消失, someStaticVar不受影响。

In this case Foo is a class, so it is a reference type. 在这种情况下, Foo是一个类,因此它是一个引用类型。 A variable of type Foo is really just a pointer to a location in memory where the Foo object actually is stored. Foo类型的变量实际上只是指向实际存储Foo对象的内存中的位置的指针。

When saying that the static variable has a constant memory address it is not saying that the value of that memory address is constant. 当说静态变量具有恒定的内存地址时, 并不是说该内存地址的值是常量。 The address of the pointer to the Foo object won't change, but the number (in this case, address) that is stored in that fixed memory location can easily vary between various potential Foo objects (or null ). 指向Foo对象的指针的地址不会改变,但存储在该固定存储器位置的数字(在这种情况下,地址)可以很容易地在各种潜在的Foo对象(或null )之间变化。

Beyond that, since C# is a managed language and not an unmanged language, it's not even true to say that the static variable will have a constant memory address. 除此之外,由于C#是托管语言而不是无人管理语言,因此静态变量将具有恒定的内存地址甚至都不是真的。 It's certainly possible , but it's really an implementation detail of the memory manager of C# that you shouldn't be relying on. 这当然是可能的 ,但它确实是C#的内存管理器的实现细节,你不应该依赖它。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 在方法中枚举静态变量并将其设置为null时会发生什么 - What happens when a static variable is set to null while it's being enumerated in a method 在C#中调用静态方法会发生什么? - What happens when you call a static method in C#? 在Class中分配静态变量 - Assign static variable inside Class 当对象变量的引用被重新分配时会发生什么? - What happens to an object variable when it's reference is reassigned? 将对象分配给变量内部的引用,而不是变量 - Assign object to reference inside variable, instead the variable C#中的static变量有什么用? 什么时候使用它? 为什么我不能在方法内部声明 static 变量? - What is the use of static variable in C#? When to use it? Why can't I declare the static variable inside method? 在方法内分配变量值 - Assign variable values inside method 静态方法内的变量共享 - Variable sharing inside static method 公共实例变量访问错误:“非静态字段,方法或属性需要对象引用......” - Public instance variable access error: “An object reference is required for the non-static field, method, or property…” 方法范围变量的事件会怎样? - What happens to the event of method scoped variable?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM