Ответ 1
Посмотрим на код, который был сгенерирован (оптимизация на, Win32 target, 10.2 Tokyo):
Project152.dpr.34: Arr := TArray<Integer>.Create(1, 2, 3, 4, 5);
004D0D22 8D45F8 lea eax,[ebp-$08]
004D0D25 8B15B84B4000 mov edx,[$00404bb8]
004D0D2B E858BFF3FF call @DynArrayClear
004D0D30 6A05 push $05
004D0D32 8D45F8 lea eax,[ebp-$08]
004D0D35 B901000000 mov ecx,$00000001
004D0D3A 8B15B84B4000 mov edx,[$00404bb8]
004D0D40 E81FBEF3FF call @DynArraySetLength
004D0D45 83C404 add esp,$04
004D0D48 8B45F8 mov eax,[ebp-$08]
004D0D4B C70001000000 mov [eax],$00000001
004D0D51 8B45F8 mov eax,[ebp-$08]
004D0D54 C7400402000000 mov [eax+$04],$00000002
004D0D5B 8B45F8 mov eax,[ebp-$08]
004D0D5E C7400803000000 mov [eax+$08],$00000003
004D0D65 8B45F8 mov eax,[ebp-$08]
004D0D68 C7400C04000000 mov [eax+$0c],$00000004
004D0D6F 8B45F8 mov eax,[ebp-$08]
004D0D72 C7401005000000 mov [eax+$10],$00000005
004D0D79 8B55F8 mov edx,[ebp-$08]
004D0D7C 8D45FC lea eax,[ebp-$04]
004D0D7F 8B0DB84B4000 mov ecx,[$00404bb8]
004D0D85 E842BFF3FF call @DynArrayAsg
и
Project152.dpr.12: SetLength(Result, 5);
004D0CB2 6A05 push $05
004D0CB4 8BC3 mov eax,ebx
004D0CB6 B901000000 mov ecx,$00000001
004D0CBB 8B15B84B4000 mov edx,[$00404bb8]
004D0CC1 E89EBEF3FF call @DynArraySetLength
004D0CC6 83C404 add esp,$04
Project152.dpr.13: Result[0] := 1;
004D0CC9 8B03 mov eax,[ebx]
004D0CCB C70001000000 mov [eax],$00000001
Project152.dpr.14: Result[1] := 2;
004D0CD1 8B03 mov eax,[ebx]
004D0CD3 C7400402000000 mov [eax+$04],$00000002
Project152.dpr.15: Result[2] := 3;
004D0CDA 8B03 mov eax,[ebx]
004D0CDC C7400803000000 mov [eax+$08],$00000003
Project152.dpr.16: Result[3] := 4;
004D0CE3 8B03 mov eax,[ebx]
004D0CE5 C7400C04000000 mov [eax+$0c],$00000004
Project152.dpr.17: Result[4] := 5;
004D0CEC 8B03 mov eax,[ebx]
004D0CEE C7401005000000 mov [eax+$10],$00000005
Итак, понятно, что код, созданный для вызова "конструктор" , просто оптимизирован.
Как вы можете видеть, сначала код "конструктор" очищает, выделяет и заполняет анонимный массив (at [ebp-$08]
), а в конце присваивает его переменной Arr
(at [ebp-$04]
). В основном это происходит медленнее.
В более новых версиях существует третий способ:
Arr := [1, 2, 3, 4, 5];
Но это создает тот же самый код, что и синтаксис "конструктор" . Но вы можете ускорить это:
const
C_ARR = [1, 2, 3, 4, 5]; // yes, dynarray const!
и
Arr := C_ARR;
Это просто генерирует динамический массив один раз, с подсчетом ссылок -1 и в цикле просто выполняет присваивание:
Project152.dpr.63: Arr := C_ARR;
004D0E60 8D45FC lea eax,[ebp-$04]
004D0E63 8B15C4864D00 mov edx,[$004d86c4]
004D0E69 8B0DB84B4000 mov ecx,[$00404bb8]
004D0E6F E858BEF3FF call @DynArrayAsg
Замечание:
Но, как прокомментировал @DavidHeffernan, в реальном программировании эти различия в производительности вряд ли когда-либо будут замечены. Обычно вы не инициализируете такие массивы в жестких циклах, и в разовой ситуации разница составляет несколько наносекунд, которые вы не заметите в течение всего запуска программы.
Замечание 2:
Кажется, есть какая-то путаница. Тип TArray<Integer>
точно такой же, как array of Integer
. Для динамических массивов также классы или некоторые другие оболочки. Это простые динамические массивы и ничего больше. Синтаксис конструктора может применяться к обоим. Единственное различие заключается в совместимости типов. TArray<Integer>
может использоваться как объявление типа ad-hoc, а все TArray<Integer>
совместимы с типом.