Im Falle von String bewirkt es vor allem, dass die automatische Referenzzählung deaktiviert und grade KEINE lokale Kopie erzeugt wird.
Wird die Referenzzählung wirklich deaktiviert oder wird es der ARC nur mitgeteilt, dass die String-Variable noch woanders benötigt wird?
Ist eigentlich nur ein Interna. Konkret wird bei konstanten Strings der RefCount immer auf -1 gesetzt, um zu verhindern, dass der Speicher für den String ungewollt freigegeben wird. Die Online-Hilfe dokumentiert dieses Verhalten
hier:
Zitat:
For string literals, the compiler generates a memory block with the same layout as a dynamically allocated string, but with a reference count of -1. String constants are treated the same way, the only difference from literals being that they are a pointer to a -1 reference counter block.
When a pointer to a string structure (source) is assigned to a string variable (destination), the reference counter dictates how this is done. Usually, the reference count is decreased for the destination and increased for the source, as both pointers, source and destination, will point to the same memory block after the assignment.
If the source reference count is -1 (string constant), a new structure is created with a reference count of 1. If the destination is not nil, the reference counter is decreased. If it reaches 0, the structure is deallocated from the memory. If the destination is nil, no additional actions are taken for it. The destination will then point to the new structure.
Im Grunde geht es bei
const S: String
weniger um den RefCounter ansich, sondern unnötige lokale Kopien und Speicheroperationen. Wenn man sich mal anschaut, wie eine leere Funktion mit String Parameter ohne
const
oder
var
aussieht:
Code:
00822538 55 push ebp
00822539 8BEC mov ebp,esp
0082253B 51 push ecx
0082253C 8945FC mov [ebp-$04],eax
0082253F 8B45FC mov eax,[ebp-$04]
00822542 E82D79BEFF call @UStrAddRef
00822547 33C0 xor eax,eax
00822549 55 push ebp
0082254A 686B258200 push $0082256b
0082254F 64FF30 push dword ptr fs:[eax]
00822552 648920 mov fs:[eax],esp
00822555 33C0 xor eax,eax
00822557 5A pop edx
00822558 59 pop ecx
00822559 59 pop ecx
0082255A 648910 mov fs:[eax],edx
0082255D 6872258200 push $00822572
00822562 8D45FC lea eax,[ebp-$04]
00822565 E82678BEFF call @UStrClr
0082256A C3 ret
0082256B E9C86DBEFF jmp @HandleFinally
00822570 EBF0 jmp $00822562
00822572 59 pop ecx
00822573 5D pop ebp
00822574 C3 ret
Im Vergleich zu einer Funktion mit
const
bzw.
var
String-Parameter:
Code:
00822578 55 push ebp
00822579 8BEC mov ebp,esp
0082257B 51 push ecx
0082257C 8945FC mov [ebp-$04],eax
0082257F 59 pop ecx
00822580 5D pop ebp
00822581 C3 ret
Hier sieht man ganz gut, dass man durch diese kleine Optimierung doch deutlich Overhead einspart.