Sie Fragen über Implementierungsdetails, so die Antwort von der speziellen Implementierung ab. Lassen Sie uns eine Version des Programms berücksichtigen, die tatsächlich kompiliert:
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;
}
}
hier ist, was auf Microsofts geschieht 4.0 CLR, läuft C# 4.0, in Debug-Modus.
An diesem Punkt des Stapelrahmenzeiger in dem Register ebp kopiert worden:
Hier ordnen wir Heap-Speicher für das neue Objekt.
A a1 = new A();
mov ecx,382518h
call FFE6FD30
Das gibt einen Verweis auf ein Heap-Objekt in EAX zurück. Wir speichern die Referenz im Stack-Slot ebp-48, einem temporären Slot, der keinem Namen zugeordnet ist. Denken Sie daran, dass a1 noch nicht initialisiert wurde.
mov dword ptr [ebp-48h],eax
Nun nehmen wir die Referenz wir gerade auf dem Stapel gespeichert und kopieren Sie sich in ECX, die für den „diesen“ Zeiger auf den Aufruf den Ctor verwendet werden.
mov ecx,dword ptr [ebp-48h]
Jetzt rufen wir den Ctor.
Jetzt kopieren wir den im temporären Stack-Slot gespeicherten Verweis erneut in das Register eax.
mov eax,dword ptr [ebp-48h]
Und nun kopieren wir die Referenz in EAX in Stapel Schlitz EBP-40, die a1 ist.
mov dword ptr [ebp-40h],eax
Jetzt müssen wir a1 in EAX holen:
a1.VarA = 5;
mov eax,dword ptr [ebp-40h]
Denken Sie daran, eax ist jetzt die Adresse der Halde zugewiesenen Daten für die Sache von a1 verwiesen. Das VarA Feld dieser Sache ist, vier Bytes in das Objekt, so speichern wir 5 in dem:
mov dword ptr [eax+4],5
Jetzt haben wir eine Kopie der Referenz in dem Stapel-Steckplatz für a1 in EAX machen, und kopieren Sie dann, dass in die Stack-Slot für a2, die ebp-44 ist.
A a2 = a1;
mov eax,dword ptr [ebp-40h]
mov dword ptr [ebp-44h],eax
Und jetzt, wie Sie wieder erwarten würden wir a2 in EAX und dann die Referenz vier Bytes in Ehrerbietung 0x0A in die VarA zu schreiben:
a2.VarA = 10;
mov eax,dword ptr [ebp-44h]
mov dword ptr [eax+4],0Ah
So ist die Antwort auf Ihre Frage ist, dass Verweise auf das Objekt sind im Stack an drei Stellen gespeichert: ebp-44, ebp-48 und ebp-40. Sie sind in Registern in eax und ecx gespeichert. Der Speicher des Objekts einschließlich seines Felds wird auf dem verwalteten Heap gespeichert. Das ist alles auf x86 im Debug-Build von Microsoft CLR v4.0. Wenn Sie wissen möchten, wie das Zeug auf dem Stack gespeichert, gehäuft und in einer anderen Konfiguration registriert wird, könnte es völlig anders aussehen. Referenzen könnten alle auf dem Heap oder alle in Registern gespeichert werden; es könnte überhaupt keinen Stapel geben. Es hängt völlig davon ab, wie sich die Autoren des JIT-Compilers für die Implementierung der IL-Semantik entschieden haben.
Da dieser Code nicht kompiliert ist es wirklich schwer zu beschreiben, wie die Laufzeit es behandelt. Sind alle diese Anweisungen in einem Methodenkörper enthalten? Sind diese Felddeklarationen oder lokalen Variablendeklarationen? –