в другую?
Скажем, переместить из TList<> в TArray<>. Именно переместить, а не скопировать.
Если использовать метод ToArray, будет копия. Если использовать свойство List, будет просто присвоение, и при освобождении TList<> массив будет тоже уничтожен.
Правильно ли понимаю задачу: извлечь указатель массива из приватного поля TList<>.FItems и сбросить указатель в этом же поле на nil?
Ну по сути да. Только из этого указателя ещё и массив сделать.
Не совсем ясно, что понимается под "массив сделать"? Указатель - это адрес памяти, а массив - это лишь представление некоторого участка памяти (частный случай строка - это тоже массив символов).
Сам по себе указатель меня не интересует. Мне нужен массив. Если можно превратить указатель в массив всякими хаками, я не против. Потому что мне не указатель нужен, а массив. Чтобы он потом сам уничтожился при выходе из скоупа и пр. дела
Если есть переменная (по сути это именованный указатель на область памяти, т.к. по сути содержит адрес памяти и тип данных в ней). Т.е. если переменной одного типа присвоить один и тот же адрес, то они будут отображать одни и те же данные. В TList<>.FItems внутри и так массив, по сути такая же структура, что и в TArray<>. Собственно не ясно для чего делать это перемещение указателей? Если вопрос в оптимизации, то в TList<> всё сделано достаточно эффективно, чтобы минимизировать все эти операции с перемещениями блоков памяти. PS: Есть подозрение, что что-то делаете не так в логике работы с данными :(
uses Generics.Collections; type PDynArrayRec = ^TDynArrayRec; TDynArrayRec = packed record {$IFDEF CPU64BITS} _Padding: Integer; // Make 16 byte align for payload.. {$ENDIF} RefCnt: Integer; Length: NativeInt; end; var L: TList<Integer>; A: TArray<Integer>; begin L := TList<Integer>.Create; for var I := 0 to 9 do L.Add(I); PPointer(@A)^ := PPointer(L.PList)^; PDynArrayRec(PByte(A) - SizeOf(TDynArrayRec))^.Length := L.Count; PPointer(NativeInt(L.PList) + SizeOf(Pointer))^ := 0; L.Free; for var I := 0 to Length(A) - 1 do Writeln(A[I]); end.
Зачем плохому учишь??
Ну если ему пофиг, лишь бы результат - чо бы и нет?
Чтобы такое оправдать надо гигабайт в этот tlist положить...
Я генерирую список. Мне удобнее работать через TList<String>, через через TArray<String>. Результат хочу закинуть в TStringList.
Хотя тут, наверное, и через PList можно забубунить :)
Гигабайт вполне возможен.
Уверен что у тебя столько свободных страниц неразрывно будет доступно?
Вполне, почему нет? Сколько раз создавал массивы на гигабайты и даже пару десятков :)
Гигабайт указателей на строки? Или вместе с содержимым гигабайт?
100 млн строк до 20 символов, например. Строки копируются из других мест, так что по сути указатель+счётчик+т.п. хрень.
Тогда тут string не нужен, до 20 символов. Быстрее будет использовать массив, причем фиксированной длины
Это в среднем до 20, по факту может быть почти любая длина.
Как хак норм, но проще сделать как сделал, чем вот это всё.
Capacity := 0; Idx := 0; // adding if Idx <= Capacity then begin if Capacity < 16 then Capacity := 16 else if Capacity < 1024 then Capacity := Capacity * 2 else Capacity := Capacity * 3 div 2; SetLength(Arr, Capacity); end; Arr[Idx] := Value; Inc(Idx); В таком духе.
А причем тут дублирование массива?
Тут ни при чём. Это же не TList.
Что происходит при выполнении SetLength с данными в массиве ясно?
Копируются в новый массив (если места нет для расширения). Остальные не определены (если не managed type).
Ну от "суперскорости" он явно отказался.
Ок. Ваше предложение.
Без понятия. Я не в теме задачи.
Кстати, интересно сравнить скорость такого похода и TList :)
Самая быстрая скорость - это работать с первоисточником. Без копирования.
Так исходно, в "постановки задачи" была речь о требовании избежать копирование данных. В общем, варианты решения достаточно подробно уже обсудили. Какие есть дополнительные требования и ограничения, да и информация о виде поступающих данных - вам лучше известны, т.ч. и карты вам в руки )) PS: Магии не бывает, только то, что мы ещё не понимаем )) Любые обёртки имеют своей целью не получить максимальную скорость и эффективность, а упрощают выполнение типовых задач (тот же TList будет работать аналогично, при ручной корректировке его Capacity).
Ну так, если я работаю с Result в функции, ей не передаётся этот первоисточник при вызове как скрытый параметр?
Ну в TList там куча какой-то оптимизации, Internal***-функции и пр. А без копирования при заполнении массива как, если я не знаю финальный размер. Поэтому только так.
Разве трудно передать ссылку куда надо?
ну например цепочка блоков с данными. если нужен o(1) доступ - то повыерх них массив указателей. Так Delphi RTL работает с Windows, есть там в ней что-то типа MakeAtom или makecallback, которая исторически течет памятью в серверах при неудачных добавлениях/отменах этих элементов. вообще, для дельфи полно разных контейнеров/коллекций с разными свойствами, в том же JCL, или на Торри порыться Другой вопрос ЧТО именно надо, какие виды работы насколько часто, какой размер данных, какая цена копирования и т.д. Может быть банальный односторонний связанный список будет быстрее всего 😊
исправление капасити, если индекс МЕНЬШЕ или равен капасити? не БОЛЬШЕ или равен?
Конечно >=. Писал с телефона.
Обсуждают сегодня