【问题标题】:Where does an object reference live and what happens when you pass an object reference by reference?对象引用在哪里存在,当您通过引用传递对象引用时会发生什么?
【发布时间】:2012-03-18 11:36:59
【问题描述】:

在 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'?

【问题讨论】:

    标签: heap-memory ref stack-memory


    【解决方案1】:

    我的理解是在 // POINT A - 你已经创建了四个 MyObject 的实例。这四个实例位于堆中。

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

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

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

    我的理解是在 // POINT B - 你创建了一个新的 引用名为“o1”的“Alpha”。该引用被添加到并存在 在堆栈上。当方法返回时,该引用被删除。

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

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

    现在我们进入您问题的棘手部分。 o2 是不同类型的引用。它不是对堆上对象的引用,而是实际上是Foo 对象上的object2 字段的别名(如您所料)。不过,o2 仍然在短期存储中占据空间,因为它仍然是方法的参数。

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

    【讨论】:

      猜你喜欢
      • 2017-06-20
      • 2014-05-27
      • 2017-08-19
      • 2015-06-18
      • 2017-09-11
      • 2022-06-27
      • 2019-03-02
      • 2012-10-08
      相关资源
      最近更新 更多