首頁>Program>source

如果有人能告诉我我是否了解我,我將不胜感激:

class X
{
   A a1=new A(); // reference on the stack, object value on the heap
   a1.VarA=5;    // on the stack - value type
   A a2=a1;      // reference on the stack, object value on the heap
   a2.VarA=10;   // on the stack - value type         
}

也都是 a1a2 引用在堆棧上,而其"物件"值在堆棧上.但是 VarA呢 變數,其仍然是纯值型別?

class A
{
   int VarA;
}
最新回復
  • 5月前
    1 #

    您正在詢問有關實施细节的問题,因此答案將取決於特定的實施.让我们考虑一下實際編譯的程式版本:

    class A { public int VarA; }
    class X
    {
        static void Main(string[] args)
        {
            A a1 = new A();
            a1.VarA = 5;
            A a2 = a1;
            a2.VarA = 10;
        }
    }
    

    這是在除錯模式下執行C#4.0的Microsoft CLR 4.0上發生的事情。

    這時,堆棧幀指標已被複製到寄存器ebp中:

    在這裏,我们為新物件分配堆記憶體。

    A a1 = new A();
    mov         ecx,382518h 
    call        FFE6FD30
    

    這將返迴對eax中堆物件的引用.我们將引用儲存在堆棧插槽ebp-48中,這是一个与任何名稱都没有關聯的臨時插槽.請記住,a1尚未初始化。

    mov         dword ptr [ebp-48h],eax
    

    現在,我们將刚才儲存在堆棧中的引用作為參考,並將其複製到ecx中,它將用作指向ctor呼叫的" this"指標。

    mov         ecx,dword ptr [ebp-48h]
    

    現在我们叫ctor。

    call        FFE8A518
    

    現在,我们將儲存在臨時堆棧插槽中的引用再次複製到寄存器eax中。

    mov         eax,dword ptr [ebp-48h]
    

    現在我们將eax中的引用複製到堆棧插槽ebp-40(即a1)中。

    mov         dword ptr [ebp-40h],eax
    

    現在我们必须將a1提取到eax中:

    a1.VarA = 5;
    mov         eax,dword ptr [ebp-40h]
    

    請記住,eax現在是a1所引用物件的堆分配資料的地址.那东西的VarA欄位是物件中的四个位元組,因此我们將5个位元組儲存到物件中:

    mov         dword ptr [eax+4],5
    

    現在,我们將a1的堆棧插槽中的引用複製到eax,然後將其複製到a2的堆棧插槽,即ebp-44。

    A a2 = a1;
    mov         eax,dword ptr [ebp-40h] 
    mov         dword ptr [ebp-44h],eax
    

    現在,正如您再次期望的那樣,我们將a2放入eax中,然後將引用的四个位元組引用以將0x0A寫入VarA:

    a2.VarA = 10;
    mov         eax,dword ptr [ebp-44h] 
    mov         dword ptr [eax+4],0Ah
    

    因此,對您的問题的答案是,對物件的引用儲存在堆棧中的三个位置:ebp-44,ebp-48和ebp-40.它们儲存在eax和ecx中的寄存器中.物件的記憶體(包括其欄位)儲存在託管堆中.這一切都在Microsoft CLR v4.0的除錯版本中的x86上完成.如果您想知道东西如何在其他配置中儲存在堆棧,堆和寄存器中,則可能完全不同.引用可以全部儲存在堆中,也可以全部儲存在寄存器中.可能根本没有堆棧.完全取決於jit編譯器的作者決定如何實現IL語義。

  • 5月前
    2 #

    嚴格来說,它取決於實現.通常,.NET開發人員不應该關心這些事情.据我所知,在Microsoft .NET的實現中,值型別的變數儲存在堆棧中(在方法中宣告時),引用型別物件的資料分配在託管堆上.但是,請記住,当值型別是類的欄位時,類資料本身会儲存在堆中(包括所有值型別欄位)。 因此,請勿將語義(值型別与引用型別)与分配規則混合使用.這件事可能有關聯,也可能没有關聯。

  • 5月前
    3 #

    我认為您可能会有一點誤会...

    通常来說,引用型別放在堆棧上,而我认為(可能是錯誤的)值型別/本地變數放在堆棧上.但是,您的A1.VarA和A2.VarA示例引用的是引用型別的欄位-该欄位与物件一起儲存在堆中...

  • 5月前
    4 #

    在這種情况下,a1.VarA將是 在堆上,因為当您完成 A a1 = new A()時会為其分配空間

    如果您只是做 int i = 5; 在將要在堆棧上的函式中,但是正如您明確宣告的那樣,將a1分配在堆上,然後与之關聯的所有值型別都將放置在堆上

  • 5月前
    5 #

    class X 
    { 
        A a1=new A(); // reference on the stack, object value on the heap 
        a1.VarA=5;    // on the Heap- value type (Since it is inside a reference type)
        A a2=a1;      // reference on the stack, object value on the heap 
        a2.VarA=10;   // on the Heap - value type (Since it is inside a reference type)
    }
    

  • c++:print从1到100的質數
  • matlab:使用双線性插值調整圖像大小,而無需調整大小