4

私はC++が次の行で何かをサポートしていると思います:

Object objects[100];

これは100個のオブジェクトをインスタンス化しますよね?Delphi(特に2007)でこれを行うことは可能ですか?それ以外のもの:

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

またはAllocate、渡されたサイズ値がサイズの100倍である関数を使用し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

反復する以外に、これを行うためのハッキーでない方法を知りません。

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個のオブジェクト参照の配列を提供するだけです。

オブジェクトの作成は2段階のプロセスです。最初のステップはメモリの割り当てです(コードも割り当てません)。2番目のステップはコンストラクター(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環境ではあまり実用的ではありません)。オブジェクトインスタンスの作成は、オブジェクトにメモリを割り当て、そのメモリ内にオブジェクトのメンバーを構築するという2段階のプロセスです。特定のオブジェクトのメモリを個別に割り当てる必要はありません。クラスタイプではなくインスタンス変数から呼び出された場合に通常のメソッドのようにコンストラクターを呼び出す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はそれをサポートしていません。

次のように、スタックまたはユーザー定義のバッファーにオブジェクトを割り当てることができるサードパーティの実装がいくつかあります。

スタック上のオブジェクト:Delphiの遺物

スタック、指定されたメモリアドレス、または任意のメモリマネージャを介してオブジェクトを割り当てます

カップルに名前を付けるだけです。

于 2012-10-27T04:55:36.323 に答える