4

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

Object objects[100];

这将实例化 100 个对象,对吗?是否可以在 Delphi(特别是 2007 年)中做到这一点?除了:

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

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

4

5 回答 5

5

您正在寻找的东西是不可能的,因为

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

所以这并不是缺少“糖语法”。


为了完整披露:

  • Delphi 还支持允许静态分配对象的遗留“旧对象模型”(Turbo Pascal 对象模型);
  • 动态对象分配本身并不会阻止自动对象实例化语法,但会使这种语法不受欢迎;
  • 自动对象实例化语法是不可能的,因为 Delphi 没有默认构造函数:Delphi 编译器从不隐式实例化对象,因为它不知道调用什么构造函数。
于 2012-10-26T13:35:54.507 回答
5

虽然你不能用对象做你想做的事,但如果你的对象比较简单,你也许可以通过使用记录数组来得到你想要的。

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

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

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

于 2012-10-26T14:08:19.467 回答
2

除了迭代之外,我不知道有任何非 hacky 方法可以做到这一点:

var
  MyObjects: array[0..99] of TMyObject;
  i: Integer;
begin
  for i := 0 to 99 do
    MyObjects[i] := TMyObject.Create;
end;
于 2012-10-26T13:25:28.887 回答
1

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

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

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

许多 VCL 类没有额外的构造函数。他们只有一个什么都不做的空构造函数。在这种情况下,没有必要调用它。

例如,要获取字符串列表数组,您可以使用以下代码,根据此示例进行调整

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);

因此,虽然此过程可以为您节省可忽略的时间,并且理论上可能更节省内存(更少碎片),但您仍然需要循环。没有捷径。

于 2012-10-26T13:42:20.790 回答
1

这在 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 不支持。

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

堆栈上的对象:德尔福遗物

在堆栈上、指定内存地址或通过任何内存管理器分配对象

仅举一对夫妇的名字。

于 2012-10-27T04:55:36.323 回答