Nur wüsste ich halt gern, was bei anderen Typen passiert. Wann bzw. ob diese referenziert werden. Und das steht nirgendwo vernünftig erklärt. Danke zumindest an dieser Stelle für die Records. Ich gehe mal davon aus, dass es bei Integern und arrays entsprechen ähnlich zu statten geht.
Triviale Typen wie Integer werden immer direkt in ein Register geschoben oder auf den Stack gepusht. Vollkommen egal, ob du
const
verwendest oder nicht. Dynamische Arrays verhalten sich eigentlich 1 zu 1 wie Strings (Ref-Count Mechanik, Copy on Write, etc). Statische Arrays (
array[n..m] of Integer
) wie folgt:
Ohne
const
:
Code:
Unit2.pas.29: begin
005CE298 55 push ebp
005CE299 8BEC mov ebp,esp
005CE29B 83C4A0 add esp,-$60 // Speicher für Elemente auf dem Stack reservieren
005CE29E 56 push esi
005CE29F 57 push edi
005CE2A0 8BF0 mov esi,eax
005CE2A2 8D7DA0 lea edi,[ebp-$60]
005CE2A5 B918000000 mov ecx,$00000018
005CE2AA F3A5 rep movsd // Elemente kopieren
Unit2.pas.31: end;
005CE2AC 5F pop edi
005CE2AD 5E pop esi
005CE2AE 8BE5 mov esp,ebp
005CE2B0 5D pop ebp
005CE2B1 C3 ret
Mit
const
:
Code:
Unit2.pas.34: begin
005CE2B4 55 push ebp
005CE2B5 8BEC mov ebp,esp
005CE2B7 51 push ecx
005CE2B8 8945FC mov [ebp-$04],eax
Unit2.pas.36: end;
005CE2BB 59 pop ecx
005CE2BC 5D pop ebp
005CE2BD C3 ret
Übergabe erfolgt auch hier erstmal immer als Referenz. Wie man sieht wird aber direkt zu Begin der Funktion eine lokale Kopie erzeugt - obwohl ich die Werte des Arrays nichtmal modifiziere. Meine Testfunktion ist komplett leer.
Als Faustregel verwende ich
const
ausnahmslos immer, wenn ich Strings, Arrays (egal welcher Art) oder Records übergebe. "Pass by reference" ist schon deutlich performanter als "pass by value" - in Delphi besonders (z.B. aufgrund des Ref-Count Overheads). Bei Objekten (die in Delphi ja eh immer Zeiger auf einen Speicherbereich auf dem Heap darstellen) und allen trivialen Datentypen lasse ich das
const
konsequent weg. "Richtige" const-correctness - wie z.B. in C++ - unterstüzt Delphi für Objekte eh nicht und bei den trivialen Typen macht es schlicht und einfach eh keinen Unterschied. Die sind ja immer konstant, solange man kein
var/out
verwendet.