我需要一个数组,它针对运行时的一次性初始化进行了优化,具有给定的长度。所以内存应该在运行时分配,但我不需要改变它的长度。
是否有纯动态数组以外的数组类型? (它似乎不是这项任务的最佳选择)
如果初始化的数组可以通过指针迭代进行索引,那么奖励就是,所以它的所有元素都在内存中连续分配。
这只是一个没有经验的程序员的白日梦,还是有可能实现这一目标?
我可以想象用手动内存分配来做到这一点,但也许还有另一种方式。
修改
我主要担心的是数组的读写速度。
答案 0 :(得分:4)
只需使用外部Count: integer
变量,并使用动态数组长度作为数组的“容量”。如果数组的初始容量定义良好,它将避免大多数内存分配。
实际上,TList<T>
单元中定义的System.Generics.Collections
正在使用此方案:它在内部存储一个数组,但它有自己的Count
属性。我怀疑这就是你要找的东西。
对于更低级别的东西,具有更多功能(如JSON或二进制序列化,或通过一个或多个属性的散列快速查找),您可以查看我们的TDynArray dynamic array wrapper。这些只是现有动态数组的包装器,而不是像TList<T>
这样的数据持有者。它们使用的是Delphi 5或更早版本,也适用于FPC。
答案 1 :(得分:3)
您可以在通用类型中封装您想要的内容。像这样:
type
TFixedLengthArray<T> = record
strict private
FItems: TArray<T>;
FLength: Integer;
function GetItem(Index: Integer): T; inline;
procedure SetItem(Index: Integer; const Value: T); inline;
public
property Length: Integer read FLength;
property Items[Index: Integer]: T read GetItem write SetItem; default;
class function New(const Values: array of T): TFixedLengthArray<T>; static;
end;
{ TFixedLengthArray<T> }
class function TFixedLengthArray<T>.New(const Values: array of T): TFixedLengthArray<T>;
var
i: Integer;
begin
Result.FLength := System.Length(Values);
SetLength(Result.FItems, Result.FLength);
for i := 0 to Result.FLength-1 do begin
Result.FItems[i] := Values[i];
end;
end;
function TFixedLengthArray<T>.GetItem(Index: Integer): T;
begin
Result := FItems[Index];
end;
procedure TFixedLengthArray<T>.SetItem(Index: Integer; const Value: T);
begin
FItems[Index] := Value;
end;
像这样创建一个新的:
var
MyArray: TFixedLengthArray<Integer>;
....
MyArray: TFixedLengthArray<Integer>.New([1, 42, 666]);
访问以下内容:
for i := 0 to MyArray.Length-1 do
Writeln(MyArray[i]);
这只是包装一个动态数组。元素是连续的。一次确定数组的长度,然后创建一个新实例。
这里需要注意的一点是,类型的行为类似于引用类型,因为它的数据存储在引用类型中。也就是说,此类型的赋值运算符的行为方式与动态数组赋值的行为方式相同。
因此,如果我们有两个此类型的变量arr1
和arr2
,则会发生以下情况:
arr1 := arr2;
arr1[0] := 42;
Assert(arr2[0] = 42);
如果你想让类型表现得像真值那么你就可以在SetItem
内实现copy-on-write。
<强>更新强>
您对问题更改的编辑非常重要。事实上,你似乎更关注性能而不是封装。
上述类型中项目访问器方法的内联意味着性能特征应该接近于数组的性能特征。访问仍然是O(1)
,但是内联器/优化器很弱并且无法发出最佳代码是非常合理的。
在您决定必须使用数组来获得绝对最终性能之前,请先进行一些真实的基准测试。在我看来,从数组读取/写入的代码确实是一个瓶颈。很可能瓶颈将是你对数组中的值所做的事情。