簡體   English   中英

對象類原語類型堆棧和堆

[英]Object Class Primitive Types Stack and Heap

首先,如果聽起來太愚蠢,我道歉。 但我總是發現自己提出以下問題。

由於對象類是.Net中所有類的最終基類,而類是引用類型,引用類型存儲在堆上,因此甚至可以進入堆棧。 我知道原始類型存儲在堆棧中,這就是我感到困惑的地方。

以int32為例,如果它的一個類及其基類是object,那么它的引用類型應該在堆上。 怎么去堆疊。

如果它不是一個類,那么我們怎么能這樣做

int i = 1;
object obj = i;  

既然我做不了類似的事情

int i = 1;
MyClass myObj = i;

編輯

從我得到的答案來看,int是結構而不是類。 仍然令人困惑的是值類型的基類是如何引用類型(對象)而它的值類型不是引用類型。

另一點是“屬於類的值類型不會存儲在堆棧中”,我想一切都在類中,甚至是控制台程序中的Main方法。 對我來說,這意味着所有變量都以某種方式屬於一個類? 那他們怎么去堆疊?

首先,如果聽起來太愚蠢,我道歉。 但我總是發現自己提出以下問題。

這些是非常常見的問題。

由於對象類是.Net中所有類的最終基類,而類是引用類型,引用類型存儲在堆上,因此甚至可以進入堆棧。

你很困惑很多事情。 讓我們從:

  • 值類型的實例是值。
  • 引用是一個值。
  • 引用是指 引用類型實例 (或者它是null,在這種情況下它什么都沒引用。)

好的,現在我們知道有三種東西,其中兩種是價值觀。

現在讓我們正確陳述你的句子:

對象類是.NET中所有類的最終基類。 類的所有實例都是引用類型的實例。 引用類型的所有實例都存儲在堆上。 如何存儲在堆棧中?

現在我們正確地提出了問題,答案很明確。 值類型的 引用實例可以進入堆棧。

讓我們繼續。

我知道原始類型存儲在堆棧中,這就是我感到困惑的地方。

從你的詞匯中消除“原始類型”這個詞; 這毫無意義。 讓我們改寫一下:

我知道值類型的實例存儲在堆棧中

不,你不知道 ,因為為了算作知識 ,陳述必須是真的。 那句話是錯誤的。 值存儲在變量中。 變量要么是長壽命的,要么是短命的。 短期變量在堆棧上。 長期存在的變量在堆上。

以int32為例,如果它的一個類及其基類是object,那么它的引用類型應該在堆上。

Int32不是一個類。 這是一個結構。 它不是參考類型。

仍然令人困惑的是值類型的基類是如何引用類型(對象)而它的值類型不是引用類型。

瑪麗是個母親。 她是女性。 她的孩子也都是女性嗎?

怎么去堆疊。

當整數存儲在短期變量中時,整數在堆棧上。

當引用存儲在短期變量中時,引用將進入堆棧。

值是引用還是值類型的實例是無關緊要的; 重要的是變量存在多長時間

如果它不是一個類,那么我們怎么能這樣做

int i = 1;
object obj = i;  

好問題。 生成一個特殊類。 認為這是:

class BoxedInt 
{
    int value;
    public BoxedInt(int v) { this.value = v; }
    public int Unbox() { return this.value; }
}

那么你的程序片段是:

int i = 1;
object obj = new BoxedInt(i);

接着

int j = (int)obj;

是相同的

int j = ((BoxedInt)obj).Unbox();

另一點是“屬於類的值類型不會存儲在堆棧中

更好的說法是:引用類型的字段是長期存在的變量。 因此它們存儲在堆上。

我想一切都在一個類中,甚至是控制台程序中的Main方法。

是的,所有代碼都在類或結構中。

對我來說,這意味着所有變量都以某種方式屬於一個類?

不,局部變量不是類的成員。

我住在一個黃色的房子里。 因此里面的所有物體都是黃色的嗎?

那他們怎么去堆疊?

普通方法中的局部變量是短暫的,因此它會進入堆棧。

只需停止將堆棧視為與存儲的數據類型有關。 堆棧與存儲什么類型的數據無關。 想想變量 堆棧是短期變量的地方。 堆是長壽命變量的地方。 變量的類型無關緊要。

Int32不是一個類。它是一個structstructs由編譯器專門處理。

object obj = i;  

這叫拳擊 因為所有類都是從對象隱式繼承的,所以你可以為object指定任何東西。你應該看一下這個文檔 ,還有成千上萬的關於裝箱和拆箱的文章。

來自MSDN:

Boxing是將值類型轉換為類型對象或由此值類型實現的任何接口類型的過程。 當CLR選中一個值類型時,它將值包裝在System.Object中並將其存儲在托管堆上。

以下是一些可能有用的參考資料

  1. struct(C#參考)
  2. 類型(C#參考)
  3. 值類型和引用類型
  4. 拳擊和拆箱
  5. 關於價值類型的真相 - Eric Lippert

- 相關問題

  1. 參考和值類型方案

  2. c#中的引用類型和值類型有什么區別?

Int32是ValueType,因此它將在堆棧中分配。 關鍵字int指的是struct System.Int32


.net中的value types分為value typesreference types

值類型是堆棧分配或在結構中內聯分配。

引用類型是堆分配的

值類型包括兩個主要類別:

  • 結構{布爾,數字,自定義}
  • 枚舉

引用和值類型都是從最終基類Object派生的。

如果值類型必須像對象一樣運行,則在堆上分配使值類型看起來像引用對象的包裝器,並將值類型的值復制到其中。 標記包裝器,以便系統知道它包含值類型。 此過程稱為裝箱,反向過程稱為拆箱。

請參考這里

原始數據類型是值類型,它們的大小是在編譯時定義的,因此編譯器將它們推送到堆棧以便更快地訪問,而引用類型只是指向存儲在堆上的對象的起始地址的指針,並且它的內存未在編譯時分配(已分配)在運行時)。

你不能這樣做

 int i  = null; // Because it's value type and need some value 
 (Default is 0) here int is alias to Int32 which is structure and
  structure is value type and same is for other primitives 

簡短回答:

  • System.Object類型不是“類”,但System.Object類型的實例是引用類型。
  • 當類型B繼承自類型A唯一隱含的是B獲取A的所有publicprotected非靜態方法,屬性和事件。
  • 類是引用類型,始終在堆上分配。
  • 結構是值類型, 可以在堆棧,堆或CPU寄存器上分配。

基本上,值類型在內存中可以有兩種不同的表示(盒裝和非盒裝),而引用類型在內存中只有一種表示。


更長的答案:

首先,你絕對可以這樣做:

int i = 1;
MyClass myObj = i;

只需將MyClass定義為:

class MyClass
{
    int i;

    public MyClass(int i)
    {
            this.i = i;
    }

    public static implicit operator MyClass(int i)
    {
        return new MyClass(i);
    }
}

(請注意,在此示例中,類MyClass的字段i 是堆分配的,即使它是值類型)

其次,值類型不一定存儲在堆棧中,如下所示:

  • 屬於class值類型字段
  • 關閉本地值類型變量(即由閉包捕獲的變量)

現在,當類型B繼承自類型A ,這意味着只有 B獲取A的所有propertiesmethodsevents 它沒有規定如何分配B實例。

暫無
暫無

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

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