2012-02-28 35 views
1

在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; 
     } 

我的理解是,在// A點 - 你已經創建的MyObject的四個實例。這四個實例存在於堆中。 - 你有四個引用這些實例。 問題1:他們住在哪裏?

我的理解是在// POINT B - 您已經創建了一個名爲'o1'的'Alpha'的新參考。該引用被添加到並在棧上生存。當方法返回時,該引用被刪除。
- 您有一個名爲'o2'的參考。 問題2:這是一個新的參考,被添加到並在棧上生活並引用'object2'引用?或者'o2'只是代碼中維護的別名(而不是內存),實際上內存中仍然只有一個引用'Bravo',稱爲'object2',當這段代碼實際執行時,'o2.foo'被處理作爲'object2.foo'?

回答

1

我的理解是在// POINT A - 你已經創建了4個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根到達的參考文獻是確定是否可以安全收集特定物體的參考。

+0

完美答案 - 謝謝! – chopperdave 2012-02-29 00:01:16

相關問題