Arrays 运行时索引为负的数组

Arrays 运行时索引为负的数组,arrays,delphi,Arrays,Delphi,我有点卡住了。我想要一个这样的数组: 整数的数组[-3..Index,1..otherIndex] 但我还需要在运行时根据给定的参数初始化这个数组。 因此,启动时未设置索引和其他索引 我想我不能在动态数组中初始化负索引,但我如何在运行时初始化这样一个静态数组?将数组包装在记录中 type TMyArray = record private FData: array of integer; ..... public class function New(Siz

我有点卡住了。我想要一个这样的数组:

整数的数组[-3..Index,1..otherIndex]

但我还需要在运行时根据给定的参数初始化这个数组。 因此,启动时未设置
索引
其他索引


我想我不能在动态数组中初始化负索引,但我如何在运行时初始化这样一个静态数组?

将数组包装在记录中

type
  TMyArray = record
  private 
    FData: array of integer;
    .....
  public
    class function New(Size1, Size2: cardinal): TMyArray; static;
    function Free;  //only needed if you utilize GetMem.
    property Item[x, y: integer]: integer read GetItem write SetItem; default;
  end;
New
函数中,使用SetLength初始化数组。
SetLength(Result.FData,SizeX*SizeY)

GetItem
/
SetItem
对中,您将3添加到
x
索引中/从
y
索引中减去1,从而访问从0开始的实际数组

GetMem
另一种方法是使用GetMem分配内存块。
请注意,GetMem不会将其内存归零,因此如果要对数组进行归零初始化,则必须调用
ZeroMemory
来清理缓冲区。
GetItem
然后看起来像:

{$pointermath on}

TMyArray = record
private
  FData: PInteger;
  FSizeX, FSizeY: cardinal; //The size of the array.
  .....

//You can use the same code for dynarray and GetMem.
function TMyArray.GetItem(x,y: integer): integer;
begin
  //Inc(x,3); Dec(y,1);
  Result := FData[(x+3)+(y-1)*FSizeX];
end;
因为
Item
是默认属性,所以您可以只写
i:=MyArray[-3,2]

清理
如果使用动态数组,当记录超出范围时,Delphi将自动为您清理内存。
如果使用
GetMem
,则必须自己进行清理

但是,可以使用记录技巧中的接口添加自动清理/析构函数,请参见和

如果您有一个下限(例如-high(smallint)),您可以执行以下操作:

type
  TNegIntArr = Array[-High(SmallInt)..High(SmallInt)] of Integer;
  PNegIntArr = ^TNegIntArr;


procedure use(numNeg : integer; arrLen : integer);
var buf : TIntegerDynArray;
    arr : PNegIntArr ; 
begin
     SetLength(buf, arrLen);
     arr := @buf[numNeg];

     dec(PByte(arr), Cardinal(@arr ^[0]) - Cardinal(@arr^[Low(TNegIntArr)]);

     // you can now savely access the array:
     for counter := -numNeg to arrLen - numNeg - 1 do
         arr^[counter] := counter;
end;

从计算角度来看,这是非常理想的(没有过程调用),但在中也有点危险,因为没有启用范围检查。

分配一个大小合适的动态数组,并将其包装在执行索引计算的代码中。或者使用GetMem使其更简单。此声明遵守常量表达式规则(请参阅文档)。当我尝试使用新方法访问FData时,我会得到一个“E2124”。记录类型中不允许使用默认指令,至少我的编译器是这么说的。@Vollmilchbb:新函数应编码为SetLength(Result.FData,FSizeX*FSizeY)。由于它是一个静态函数,因此没有“Self”,函数结果是需要分配的新数组。
函数TMyArray.GetItem(x,y:integer):integer;开始结果:=FData[(x+3)+(y-1)*FSizeX];结束使编译器有更多机会成功优化Isuspect@Vollmilchbb,记录中不允许使用默认的
。我刚才跳过了一个
。有许多更干净的选项不需要函数调用