-
В других языках, таких как С++, вы должны сами отслеживать длину массива - как Delphi знает длину моего массива? Есть ли внутреннее, скрытое целое число?
-
Лучше ли для критически важных частей не использовать Length(), а прямое целое управляемое мной?
Как работает функция Length() в Delphi?
Ответ 1
Существует три типа массивов, а Length работает по-разному для каждого:
-
Динамические массивы: они реализованы как указатели. Указатель указывает на первый элемент массива, но "за ним" этот элемент (с отрицательным смещением от начала массива) представляет собой два дополнительных целочисленных значения, которые представляют длину массива и счетчик ссылок.
Length
читает это значение. Это то же самое, что и для типаstring
. -
Статические массивы. Компилятор знает длину массива, поэтому
Length
является константой времени компиляции. -
Открытые массивы. Длина параметра открытого массива передается как отдельный параметр. Компилятор знает, где найти этот параметр, поэтому он заменяет
Length
тем, что считывает это значение параметра.
Ответ 2
Не забывайте, что макет динамических массивов и т.д. изменится в 64-разрядной версии Delphi, поэтому любой код, который опирается на поиск длины в определенном смещении, сломается.
Я советую использовать Length()
. Если вы работаете с ним в цикле, вам может понадобиться кэшировать его, но не забывайте, что цикл for
уже кэширует завершающие границы цикла.
Ответ 3
Да, на самом деле есть два дополнительных поля с динамическими массивами. Во-первых, это число элементов в массиве с смещением -4 байтов к первому элементу, а на -8 байт смещается туда отсчет ссылок. См. статью Руди для подробного объяснения.
Во втором вопросе вам нужно будет использовать SetLength
для определения размеров динамических массивов, поэтому внутреннее поле длины будет доступно в любом случае. Я не вижу много пользы для дополнительного отслеживания размера.
Ответ 4
Поскольку Роб Кеннеди дал такой хороший ответ на первую часть вашего вопроса, я просто обращусь ко второму:
Лучше ли для критически важных частей не использовать Length(), а управлять прямым целым?
Абсолютно нет. Во-первых, как заметил Роб, компилятор делает это очень быстро получить доступ к информации, либо прочитав фиксированное смещение перед началом массива в случае динамических, используя константу времени компиляции в случае статических, и передавая скрытый параметр в случае открытых массивов, вы не получите улучшения в производительности.
Во-вторых, прямое целое, управляемое вами, не будет быстрее, но на самом деле будет использовать больше памяти (дополнительное целое число, выделенное вместе с тем, которое Delphi уже предоставляет для динамических и открытых массивов, а дополнительное целое полностью в случае статических массивов).
Даже если вы прямо читаете значение, которое Delphi хранит уже для динамических массивов, вы не получите никакой производительности по сравнению с длиной() и рискуете нарушить код, если внутреннее представление этого скрытого заголовка для массивов изменится в будущем.
Ответ 5
Есть ли внутреннее, скрытое целое число
Да.
чтобы не использовать Length(), но управляемое мной прямое целое?
Не важно.
См. Динамические массивы в Адресаторы Руди Велтиус.
P.S. Вы также можете нажать кнопку F1.