有没有办法在Delphi中实例化所需数量的对象,而无需迭代?

时间:2012-10-26 13:16:44

标签: delphi delphi-2007

我认为C ++支持以下内容:

Object objects[100];

这会实例化100个对象,对吧?是否有可能在Delphi(特别是2007年)中做到这一点?除了以外的东西:

for i:=0 to 99 do
  currentObject = TObject.Create;

或使用Allocate函数,传递的大小值是TObject大小的一百倍,因为它只是分配内存,它实际上并没有划分内存并且“给”它对象。 如果我假设c ++实例化是即时的而不是根据引擎迭代,我道歉。

5 个答案:

答案 0 :(得分:5)

你在寻找什么是不可能的,因为

  • Delphi不支持静态(堆栈分配)对象。
  • Delphi对象没有可由编译器自动调用的默认构造函数。

所以这并不缺乏'糖语法'。


为了完整披露:

  • Delphi还支持传统的“旧对象模型”(Turbo Pascal对象模型),它允许静态分配对象;
  • 动态对象分配本身不会阻止自动对象实例化语法,但会使这种语法不合适;
  • 自动对象实例化语法是不可能的,因为Delphi没有默认构造函数:Delphi编译器从不隐式实例化对象,因为它不知道要调用的构造函数。

答案 1 :(得分:5)

虽然您无法使用对象执行所需操作,但如果对象相对简单,则可以使用记录数组获得所需内容。

Delphi中的记录可以包含属性(包括setter和getter),以及类和实例方法。它们在声明时自动创建,因此声明它们的数组将创建它们而不进行迭代。

更多信息:http://docwiki.embarcadero.com/RADStudio/XE3/en/Structured_Types#Records_.28advanced.29

(我不确定何时将新功能添加到Delphi,它可能是在2007版本之后)。

答案 2 :(得分:2)

除了迭代之外,我不知道有任何非hacky方法:

var
  MyObjects: array[0..99] of TMyObject;
  i: Integer;
begin
  for i := 0 to 99 do
    MyObjects[i] := TMyObject.Create;
end;

答案 3 :(得分:1)

该声明不会创建100个对象,它只会为您提供一个包含100个对象引用的数组,这些对象引用没有任何用处。

创建对象是一个两步过程。第一步是分配内存(你的代码也没有),第二步是调用构造函数(Create方法)来初始化内存,创建其他对象等等。

分配部分可以在没有循环的情况下完成,但需要调用构造函数来初始化每个实例。

许多VCL类没有其他构造函数。他们只有空构造函数,什么都不做。在这种情况下,无需调用它。

例如,要获取字符串列表数组,可以使用以下代码adjusted from this example

type
  TStringListArray = array of TStringList;v
var
  Instances: array of Byte;

function GetStringLists(Number: Integer): TStringListArray;
var
  i: Integer;
begin
  // Allocate instance memory for all of them
  SetLength(Instances, Number * TStringList.InstanceSize);
  // Zero the memory.
  FillChar(Instances[0], Length(Instances), 0);
  // Allocate array for object references.
  SetLength(Result, Number);

  for i := 0 to High(Result) do
  begin
    // Store object reference.
    Result[i] := @Instances[i * TStringList.InstanceSize];
    // Set the right class.
    PPointer(Result[i])^ := TStringList;
    // Call the constructor. 
    Result[i].Create;
  end;
end;

获得100个字符串列表的数组:

var
  x: TStringListArray;
begin
  x := GetStringLists(100);

因此,虽然这个过程可以为您节省可忽略的时间,理论上可能更节省内存(更少碎片),但您仍然需要循环。没有简单的出路。

答案 4 :(得分:0)

Delphi中可能有点(但在Delphi环境中不太实用,除非您正在编写自定义内存管理器)。创建对象实例是一个两步过程 - 为对象分配内存,并在该内存中构造对象的成员。没有什么需要单独分配给定对象的内存。您可以分配更大的内存块并在该块内构造多个对象,利用Delphi的一个功能,如果从实例变量而不是类类型调用,则调用类似普通方法的构造函数,例如:

var
  objects: array of Byte;
  obj: TSomeClass;
begin
  SetLength(objects, 100 * TSomeClass.InstanceSize); 
  FillChar(objects[0], 0, Length(objects));
  for i := 0 to 99 do
  begin
    obj := TSomeClass.InitInstance(@objects[i * TSomeClass.InstanceSize]));
    obj.Create;
  end;
  ...
  for i := 0 to 99 do
  begin
    obj := TSomeClass(@objects[i * TSomeClass.InstanceSize]);
    obj.CleanupInstance;
  end;
  SetLength(objects, 0);
end;

这与C ++在声明一个对象实例数组时在幕后所做的事情没什么不同,只有C ++支持静态声明数组,它会自动调用构造函数和析构函数,而Delphi不支持它。

有许多第三方实现允许您在堆栈或用户定义的缓冲区中分配对象,例如:

Objects on the Stack: A Delphi Relic

Allocate objects on stack, at specified memory address, or through any memory manager

仅举几个名字。