2013-01-16 8 views
8

Ich habe zwei Datensätze mit den gleichen Feldern und einer von ihnen hat eine Reihe von Verfahren. Warum ist die Größe beider Datensätze gleich?Warum wird die Größe eines Delphi-Datensatzes nicht erhöht, wenn eine Prozedur eingeschlossen ist?

{$APPTYPE CONSOLE} 

{$R *.res} 

uses 
    System.SysUtils; 

type 
    TData = record 
    Age : Byte; 
    Id : Integer; 
    end; 

    TData2 = record 
    Age : Byte; 
    Id : Integer; 
    procedure foo1; 
    procedure foo2; 
    procedure foo3; 
    end; 

procedure TData2.foo1; 
begin 

end; 

procedure TData2.foo2; 
begin 

end; 

procedure TData2.foo3; 
begin 

end; 

begin 
    try 
    Writeln('SizeOf(TData) = '+ IntToStr(SizeOf(TData))); 
    Writeln('SizeOf(TData2) = '+ IntToStr(SizeOf(TData2))); 
    Readln; 
    except 
    on E: Exception do 
     Writeln(E.ClassName, ': ', E.Message); 
    end; 

end. 
+0

Das Hinzufügen von Methoden erhöht niemals die Instanzgröße, es gilt sowohl für das Aufzeichnen von Instanzen als auch von Objekten. – kludg

+0

@DavidHeffernan - nein, tut es nicht. Es erhöht nur Klassenmetadaten, die Instanzgröße ändert sich nicht. Die einzige Möglichkeit, die Instanzgröße anders als durch Felder zu erhöhen, besteht in Schnittstellen. – kludg

+0

@Serg Sie haben Recht, ich liege falsch. Es tut uns leid. Ich dachte, dass jede Instanz eine Kopie der VMT hatte. Ich nahm das wegen des virtuellen Methodentrenners an. Aber das funktioniert, indem Sie eine Kopie des VMT erstellen. Offensichtlich muss ich meine Fakten überprüfen, bevor ich den Mund öffne. –

Antwort

10

Das liegt daran, dass der Datensatz selbst nur die Daten enthält, aus denen der Datensatz besteht, und keine Prozeduren oder Funktionen. Die Prozeduren und Funktionen sind eine Art syntaktischer Zucker zu vermeiden, den Datensatz selbst als Parameter übergeben: self Variable, die automatisch von dem Compiler für Sie hinzugefügt wird.

Jede Methode, die Sie in einem Datensatz deklarieren haben einen anderen Parameter für die Aufzeichnung selbst, zum Beispiel:

TData2 = record 
    Age : Byte; 
    Id : Integer; 
    procedure Foo1; 
    procedure Foo2(SomeParam: Integer); 
    end; 

entspricht etwas geändert wird:

PData2 = ^TData2; 

    TData2 = record 
    Age : Byte; 
    Id : Integer; 
    end; 

    procedure TData2_Foo1(Self: PData2); 
    procedure TData2_Foo2(Self: PData2; SomeParam: Integer); 

jedes Ende auch machen nennen, ist geändert, zum Beispiel:

var 
    Data: TData2; 
begin 
    Data.Foo1; 
    Data.Foo2(1); 
end; 

wird für etwas geändert, das entspricht:

var 
    Data: TData2; 
begin 
    TData2_Foo1(@Data); 
    TData2_Foo1(@Data, 1); 
end; 

Ich habe keine zur Hand Delphi zu prüfen, ob die Parameter am Anfang oder am Ende Ihrer Parameterliste hinzugefügt werden, aber ich hoffe, Sie bekommen die Idee.

Natürlich gibt es keine echte Syntax dafür, da es on the fly vom Compiler gemacht wird und somit zum Beispiel die Prozedurnamen nicht geändert werden. Ich habe das getan, um meine Antwort leicht verständlich zu machen.

+3

+1 Implizite Self-Parameter ist zuerst in der Parameterliste –

+1

Über Speicherstruktur bei Funktion/Methodenaufrufe, siehe http://docwiki.embarcadero.com/RADStudio/XE3/en/Program_Control, die deutlich besagt, dass "Methoden die gleichen Aufrufkonventionen wie verwenden gewöhnliche Prozeduren und Funktionen, außer dass jede Methode einen zusätzlichen impliziten Parameter Self hat, der eine Referenz auf die Instanz oder Klasse ist, in der die Methode aufgerufen wird Der Parameter Self wird als 32-Bit-Zeiger übergeben. Unter der Registerkonvention verhält sich Self so, als wäre es vor allen anderen Parametern deklariert. Es wird daher immer im EAX-Register übergeben " –

+1

@ArnaudBouchez: Ich nehme an, dass bei einem 64-Bit-Ziel der an die Methode übergebene Self-Zeiger ein 64-Bit-Zeiger wäre. –

0

Prozeduren nehmen keinen Platz. Der Compiler wird sie richtig verbinden. Ihre Adressen müssen sich nicht zur Laufzeit für jeden Datensatz im Speicher befinden. Wenn Sie die Darstellung von TData2 im Speicher betrachten, werden Sie die Prozeduren nicht finden.

+1

Dies ist etwas ungenau. Prozeduren brauchen Speicher. Der Code belegt Speicher. Diese Antwort wiederholt die in der Frage angegebenen Fakten, ohne zu erklären warum. Die Antwort lautet, dass die Codeadressen zur Kompilierungszeit statisch und bekannt sind und daher nicht im Datensatz gespeichert werden müssen. –

Verwandte Themen