对象引用在哪里,以及通过引用传递对象引用时会发生什么?

时间:2012-02-28 23:27:11

标签: stack heap ref

在C#的背景下:

我们假设以下代码......

public class Foo
    {
        MrObject object1;
        MrObject object2;
        MrObject object3;
        MrObject object4;

        MrStruct struct1;
        MrStruct struct2;
        MrStruct struct3;
        MrStruct struct4;

        int i;

        public Foo()
        {
            object1 = new MrObject(1);  /// Alpha
            object2 = new MrObject(2);  /// Bravo
            object3 = new MrObject(3);  /// Charlie
            object4 = new MrObject(4);  /// Delta

            i = 1;

            InitializeComponent(); // POINT A
            ByValByRef(object1, ref object2);

        }


        public void ByValByRef(MrObject o1, ref MrObject o2)
        {
            o1.foo = 5; // POINT B
            o1 = object3; // POINT C
            o2.foo = 6; // POINT D
            o2 = object4; // POINT E
            return;
        }

我的理解是在// POINT A - 您已创建了四个MyObject实例。这四个实例存在于堆中。 - 您有四个对这些实例的引用。 问题1:他们住在哪里?

我的理解是在// POINT B - 您创建了一个名为'o1'的'Alpha'的新引用。该引用被添加到堆栈中并存在于堆栈中。当方法返回时,该引用被删除 - 你有一个名为'o2'的引用。 问题2:这是一个新的引用,它被添加到堆栈并存在于堆栈中并引用了'object2'引用?或者'o2'只是在代码中维护的别名(而不是在内存中),实际上在内存中只有一个引用'Bravo'称为'object2',当这个代码实际执行时,'o2.foo'被处理作为'object2.foo'?

1 个答案:

答案 0 :(得分:1)

  

我的理解是,在// POINT A - 你创造了四个   MyObject的实例。这四个实例存在于堆中。

右。已在堆上为每个对象分配内存。

  

您有四个对这些实例的引用。问题1:他们在哪里   住?

创建对象时,您将每个对象分配(引用)到Foo对象上的不同字段。这些字段“存活”在为Foo对象分配的内存中,这几乎肯定在堆上的某个位置。

  

我的理解是在// POINT B - 你创造了一个新的   引用名为'o1'的'Alpha'。该参考被添加到并生活   在堆栈上。当方法返回时,该引用将被删除。

是的,在POINT B,参数o1还存储对作为参数传递的MrObject的引用。 o1住在短期商店,这通常是“堆栈”。当方法结束时,用于o1的短期存储空间将可供其他用途使用,垃圾收集器将不再将o1视为已知的实时根。

  

你有一个名为'o2'的引用。问题2:这是一个新的参考   添加到堆栈并生活在堆栈上并引用'object2'   参考?或者'o2'只是代码中维护的别名(而不是代码)   内存)实际上在内存中仍然只有一个引用   'Bravo'称为'object2',当这段代码实际执行时,   'o2.foo'被视为'object2.foo'?

现在我们来看你问题的棘手部分。 o2是另一种参考。它不是对堆上对象的引用,而是实际上是object2对象上Foo字段的别名(如您所推测的)。 o2仍占据短期商店的空间,因为它仍然是方法的论据。

顺便说一下,“Bravo内存中只有一个引用”并不是你应该担心的。 可从已知GC根访问的引用决定了是否可以安全地收集特定对象。