簡體   English   中英

對象如何存儲在內存中?

[英]How are objects stored in memory?

我試圖了解如何使用 .NET Framework 將對象存儲在內存中。

給定以下person類:

public class Person
{
    public string name { get; set; }

    public int age { get; set; }
}

我相信Person類型的已啟動變量在內存中將具有以下結構: 人的記憶結構

問題:

  • 首先,他們在我的理解中是否有任何主要/明顯的缺陷? (我幾乎可以肯定有,因為以我描述的方式處理對象似乎效率低下;尤其是name指針指向字符串成員的字符集合的方式)

  • 其次,對於類的值類型成員(IE Age ),它們是存儲在對象本身中(因此在與對象相同的內存地址中),還是分配了自己的地址,然后對象指向它? (如我的圖表所示)

  • 與上面的問題類似,但是對於引用類型成員,對象是否持有指向該指針的指針? (IE 在我的圖中引用 char 集合的名稱指針)

  • 最后,如果我的Person類的成員是字段而不是屬性會有所不同嗎?

更新:根據 Sweeper & Tim 的答案更新圖表,我認為現在是正確的。

正確的圖表

注意:指針更改為引用,因為這是托管代碼。

有一些錯誤。 你弄錯了int成員,它是一個值類型。 所以沒有指針,它包含在 Person 對象的存儲中,占用 4 個字節。 name對象引用看起來也不完全正確,它指向一個 String 對象。 字符串中的字符包含在字符串的存儲中,就像int一樣。 或者換句話說,String 對象存儲的大小是可變的,只要存儲字符所需的大​​小即可。

因此,訪問 Person 對象的成員只需要取消引用兩個指針,這樣效率更高。

是的,Person 類型的變量只存儲指針。 GC 在壓縮堆時更新它。

屬性在運行時不存在,它是編譯器提供的抽象。 編譯器通常會為其分配一個字段,除非您自己提供 getter 和 setter 方法。 因此,您繪圖中的“姓名”和“年齡”實際上是字段,它們將具有不同的名稱。

在 .net 世界中,指針指向非托管內存,對象引用指向托管對象。 垃圾收集器可以隨時移動對象,因此指向它們的指針將在沒有警告的情況下被銷毀。 概念是相同的,但有區別,因為您確實可以在不安全的 C# 代碼中使用指針。 如果您抓住一個指向對象的指針,並且該對象移動,則您的指針指向任意內存空間。 但是,對象引用被保留。

至於年齡問題。 它存儲在對象本身中,在結構中占據 32 位——不是指向 int32 的引用/指針

對於引用類型成員,它持有一個引用,它在概念上與指針相同,占用 64 位空間(或 32 位,取決於體系結構),但與我上面提到的有些不同。

最后,匿名屬性實際上是在創建隱藏字段以及設置和返回這些字段的自動編寫代碼。 存儲是相同的,但通過屬性而不是直接通過字段訪問它的成本非常低。

我將從最容易回答的問題開始:

如果我的 Person 類的成員是字段而不是屬性,會有什么不同嗎?

不。代碼中的屬性只是語法糖。 編譯代碼時,這些屬性用{ get; set; } { get; set; } { get; set; }將變成帶有 getter 和 setter 的字段。

我的理解有什么重大/明顯的缺陷嗎?

是的。 當我回答以下問題時,我會提到它們。

其次,對於類(IE Age)的值類型成員,它們是存儲在對象本身中(因此與對象在相同的內存地址中),還是分配了自己的地址,然后對象指向它? (如我的圖表所示)

你的第一句話是正確的。 值類型存儲在對象中。 Person對象中沒有指向int的指針。 換句話說,你的圖表是錯誤的。

但是對於引用類型成員,對象是否持有指向該指針的指針? (IE 在我的圖中引用 char 集合的名稱指針)

在這種情況下, char[]是您已經注意到的引用類型。 但它實際上持有一堆char ,它們是值類型。 所以不,字符存儲在 char 數組中,就像Age存儲在Person的方式一樣。 另一方面,如果這是一個string[] ,則會有一個指向數組的指針,該數組將包含指向字符串對象的指針。 這也意味着你的圖表是錯誤的。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM