1

例如,当您声明动态数组时,您会这样做

var
  MyArray: array of Byte;

这样编译器就知道当它超出范围时它必须完成该变量(数组)。但我想将动态数组声明为这样的指针

var
  MyArray: Pointer;

我知道如何在运行时动态初始化(设置长度)到这样的数组。问题是编译器不知道它需要完成它。我想知道是否有办法告诉编译器在超出范围时将该指针最终确定为数组。我会告诉他当我第一次初始化数组时。

我知道这是一个 hack,我不想听到这不是正确的方法。我有一个非常具体的愿望(问题),我想知道这是否可以实现。我想这不像编译器那样使用编译器魔法。

编辑

我想保持问题简单,但有些人想知道更多,我会告诉更多。我认为这与问题无关,但无论如何,就在这里。

我想为每条记录保留 4 个字节(或 64 位系统上的 8 个字节)。它更像是一个游戏。我的想法是在变量记录 TSimpleData 中插入一个指向动态数组的指针。这类记录不接受需要最终确定的变量。完全清楚为什么。但我想知道以后是否有办法注册完成。我 99% 确定没有办法,但要求 100% 确定没有害处。波纹管是有问题的相关代码。我希望 FComplexData 作为简单指针成为 TSimpleData 的一部分。

 TSimpleData = record { do not pack this record; it is compiler-generated }
    case Byte of
      atInteger:   (VInteger: Integer);
      atCardinal:  (VCardinal: Cardinal);
      atBoolean:   (VBoolean: Boolean);
      atObject:    (VObject: TObject);
      atPointer:   (VPointer: Pointer);
      atClass:     (VClass: TClass);
      atWideChar:  (VWideChar: WideChar);
      atChar:      (VChar: AnsiChar);
    {$IFDEF AnyValue_UseLargeNumbers}
      atInt64:     (VInt64: Int64);
      atExtended:  (VExtended: Extended);
    {$ENDIF}   
  end;

  TAnyValue = packed record   private
    FValueType: TValueType;   
  {$IFNDEF AnyValue_NoInterfaces}
    FInterface: IInterface;   
  {$ENDIF}
    FSimpleData: TSimpleData;
    FComplexData: array of Byte;
    ...    
  end;
4

2 回答 2

2

没有办法按照你的要求去做。使编译器自动完成动态数组的唯一方法是声明一个动态数组。如果没有实际声明,您不能将动态数组变量“插入”到您的代码中。

声明后,您可以将该指针分配给它,它会像任何其他动态数组一样被清理。如果需要,您可以将该行为包装到一个函数中:

procedure CleanUpArray(P: Pointer);
var
  Arr: array of Byte;
begin
  Pointer(Arr) := P;
end;

如果你调用CleanUpArray(MyArray),存储在Pointer变量中的动态数组将被清理——它的引用计数减少 1,并且可能释放它的内存——尽管存储在其中的值MyArray将保持不变。

该函数之所以有效,是因为类型转换禁用了动态数组赋值语句中固有的任何引用计数代码,因此它本质上是按位复制。但是,一旦函数返回,编译器插入的变量清理代码就会运行。它注意到该变量是非空的,因此它假定该变量中有一个动态数组引用,并且该数组被清理了。

用它的真实类型声明变量要好得多。它使您编译器的生活更轻松。

于 2013-02-07T19:49:23.270 回答
0

要回答我自己的问题,没有直接的方法可以做到这一点。但由于我不会轻易放弃,所以提出了一个解决方案:

http://www.cromis.net/blog/2013/02/tanyvalue-an-attempt-to-make-the-best-variable-data-container/

它基本上完成了 Embarcadero 或 Borland 多年前应该做的事情。

于 2013-02-14T13:54:58.610 回答