Делфи копирования при записи для строки


У меня есть такой код:

function Test: string;
var
   r, s: string;
begin
   r := 'Hello';
   Writeln(NativeInt(PChar(@r[1])));
   s := r;
   Writeln(NativeInt(PChar(@s[1])));
   Result := r;
   Writeln(NativeInt(PChar(@Result[1])));
end;

Люди говорят, что delphi использует copy-on-write для строк. но вышеприведенная функция выводит 3 различных адреса для переменной, r, s и результата. Так что это сбивает с толку.. Есть ли в памяти только копия строки "Hello"?

1 5

1 ответ:

Всякий раз, когда вы берете адрес элемента строки, это считается какзапись в глазах компилятора. Теперь у вас есть необработанный указатель на внутренние части строки, и кто знает, что вы собираетесь с ним делать. Так что, с его точки зрения, он играет безопасно. Он решает сделать уникальную копию строки,так что вы можете делать любые подлые поступки, которые вы планируете сделать с вашим необработанным указателем.

Код, который вы компилируете в это:

Project2.dpr.13: r := 'Hello';
00419EF8 8D45FC           lea eax,[ebp-$04]
00419EFB BAA89F4100       mov edx,$00419fa8
00419F00 E827D2FEFF       call @UStrLAsg
Project2.dpr.14: Writeln(NativeInt(PChar(@r[1])));
00419F05 8D45FC           lea eax,[ebp-$04]
00419F08 E883D3FEFF       call @UniqueStringU
00419F0D 8BD0             mov edx,eax
00419F0F A18CE64100       mov eax,[$0041e68c]
00419F14 E853B2FEFF       call @Write0Long
00419F19 E82EB5FEFF       call @WriteLn
00419F1E E845A1FEFF       call @_IOTest
Project2.dpr.15: s := r;
00419F23 8D45F8           lea eax,[ebp-$08]
00419F26 8B55FC           mov edx,[ebp-$04]
00419F29 E8FED1FEFF       call @UStrLAsg
Project2.dpr.16: Writeln(NativeInt(PChar(@s[1])));
00419F2E 8D45F8           lea eax,[ebp-$08]
00419F31 E85AD3FEFF       call @UniqueStringU
00419F36 8BD0             mov edx,eax
00419F38 A18CE64100       mov eax,[$0041e68c]
00419F3D E82AB2FEFF       call @Write0Long
00419F42 E805B5FEFF       call @WriteLn
00419F47 E81CA1FEFF       call @_IOTest
Project2.dpr.17: Result := r;
00419F4C 8BC3             mov eax,ebx
00419F4E 8B55FC           mov edx,[ebp-$04]
00419F51 E88ED1FEFF       call @UStrAsg
Project2.dpr.18: Writeln(NativeInt(PChar(@Result[1])));
00419F56 8BC3             mov eax,ebx
00419F58 E833D3FEFF       call @UniqueStringU
00419F5D 8BD0             mov edx,eax
00419F5F A18CE64100       mov eax,[$0041e68c]
00419F64 E803B2FEFF       call @Write0Long
00419F69 E8DEB4FEFF       call @WriteLn
00419F6E E8F5A0FEFF       call @_IOTest

Вызовы UniqueStringU выполняют копирование в copy-on-write.