Fast copy of TList <T>?
Is there a quick way to copy a common TList?
Copy.Capacity := List.Count; for Item in List do Copy.Add (Item); very slow. It seems that there is no way to use CopyMemory , since I can not get the memory address of the internal array (which is obvious from the point of view of hiding information). I miss something like
List.Copy (Copy); which uses knowledge of internal representation to increase productivity. It can be done?
+8
jpfollenius
source share2 answers
For a general TList<T> simply not possible to implement the desired function. This is because copying the contents of T may require a simpler copy of memory. If T contains any managed types (i.e., Strings, interfaces, etc.), then the number of references to these managed objects should be increased.
- If your
Tcontains managed types, I doubt that you can do much better than the code that you already have. - If your
Tdoes not contain managed types, then a memory copy is viable, but you will need to create your own class to encapsulate this list, sinceTList<T>not suitable.
+8
David heffernan
source shareYou can always rethink memory.
type TListHack<T> = class(TEnumerable<T>) private FItems: array of T; FCount: Integer; public class procedure FastAdd(Source, Dest: TList<T>); end; { TListHack<T> } class procedure TListHack<T>.FastAdd(Source, Dest: TList<T>); var SourceHack: TListHack<T>; DestHack: TListHack<T>; TI: PTypeInfo; begin TI := TypeInfo(T); if not (TI.Kind in [tkInteger, tkChar, tkFloat, tkSet, tkClass, tkMethod, tkWChar, tkInt64, tkClassRef, tkPointer, tkProcedure]) then raise Exception.CreateFmt('Type %s is not supported', [TI.Name]); if Source.Count = 0 then Exit; DestHack := TListHack<T>(Dest); SourceHack := TListHack<T>(Source); if Dest.Capacity < Dest.Count + Source.Count then Dest.Capacity := Dest.Count + Source.Count; Move(SourceHack.FItems[0], DestHack.FItems[Dest.Count], Source.Count * SizeOf(T)); DestHack.FCount := DestHack.FCount + Source.Count; end; procedure TForm6.FormCreate(Sender: TObject); var Source, Dest: TList<Integer>; Arr: TArray<Integer>; begin Source := TList<Integer>.Create; Dest := TList<Integer>.Create; try Source.Add(1); Source.Add(2); Source.Add(3); Dest.Add(10); TListHack<Integer>.FastAdd(Source, Dest); Assert(Dest.Count = 4); ShowMessageFmt('%d, %d, %d, %d', [Dest[0], Dest[1], Dest[2], Dest[3]]); finally Source.Free; Dest.Free; end; TListHack<IUnknown>.FastAdd(TList<IUnknown>.Create, TLIst<IUnknown>.Create); // exception end; But it is very dangerous
+1
Jack128
source share