16

今日、コンパイラのバグ ( QC#108577 ) を発見しました。

次のプログラムはコンパイルに失敗します。

program Project1;
{$APPTYPE CONSOLE}

procedure P(M: TArray<TArray<Integer>>);
begin
  SetLength(M, 1, 2);
end;

begin
end.

コンパイラは行をギャグして、次のSetLengthように言います。

[dcc32 Error] E2029 ')' expected but ',' found

私は次のように修正できることを知っています:

procedure P(M: TArray<TArray<Integer>>);
var
  i: Integer;
begin
  SetLength(M, 1);
  for i := low(M) to high(M) do
    SetLength(M[i], 2);
end;

しかし当然のことながら、私はこれに頼る必要を避けたいと思っています。

次のバリアントはコンパイルされ、機能しているようです。

procedure P(M: TArray<TArray<Integer>>);
type
  TArrayOfArrayOfInteger = array of array of Integer;
begin
  SetLength(TArrayOfArrayOfInteger(M), 1, 2);
end;

TArray<T>これが安全であると確信するには、動的配列、キャスト、参照カウントなどの実装の詳細について十分に知りません。

これが実行時に正しいコードを生成するかどうかを何らかの方法で言うのに十分な人はいますか?

4

3 に答える 3

18

コンパイラの組み込みプロシージャSetLengthは、スタック上でその場で次元の配列を構築し、DynArraySetLength汎用かどうかに関係なく、任意の動的配列を呼び出します。ジェネリック配列が通常の動的配列と構造的に互換性がない場合、長さを設定するための同じ実装は呼び出されない可能性があります。

実際、多次元配列の代替としてのオファーのドキュメント。型キャストの代わりに使用することもできますが、どちらかを好む理由はわかりません。 DynArraySetLengthSetLengthDynArraySetLength

于 2012-09-07T17:07:30.943 に答える
3

ジェネリック実装の設計により、手動マップを使用してarray of array of Integer動作します。

しかし、ここでジェネリックを使用する利点はありません!

コードするだけです:

type
  TArrayOfArrayOfInteger = array of array of Integer;

procedure P(M: TArrayOfArrayOfInteger);
begin
  SetLength(TArrayOfArrayOfInteger, 1, 2);
end;

orを指定しない限り、そのようなTArray<>orarray of ..は値で渡され、スタックにコピーされることにも注意してください。constvar

procedure P(var M: TArrayOfArrayOfInteger);
begin
  SetLength(TArrayOfArrayOfInteger, 1, 2);
end; // now caller instance of the parameter will be resized

var A: TArrayOfArrayOfInteger;
...
A := nil;
P(A);
assert(length(A)=1);
assert(length(A[0])=2);
于 2012-09-07T16:33:41.043 に答える
2

私は最近、C++ では と が実際には異なる方法で実装されている (DynamicArray<T>はスタンドアロン クラスであるのに対し、は子孫である)という事実に悩まされていました。少なくとも、さまざまなタイプの RTTI が生成されることは確かです。Delphi コンパイラが typedefの代わりにDelphi 型の HPP ファイルに typedef を出力し始めたときに失敗し始めた私の C++ コードの一部の問題の根本的な原因はこれでした。TArray<T>DynamicArrayTArrayTObjectarray of TTArray<T>TArrayarray of ...DynamicArray

于 2012-09-07T23:26:39.357 に答える