今天我发现了一个编译器bug(
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),2); end;
我对动态数组的实现细节不够了解,TArray< T>铸造,参考计数等,以确保这是安全的.
有没有人知道足够的话说出一种方式,无论这是否会在运行时产生正确的代码?
解决方法
编译器内部过程SetLength在堆栈上即时构建一个维度数组,并为任何动态数组调用DynArraySetLength,无论是否通用.如果通用数组不会与常规动态数组结构兼容,则可能不会调用用于设置长度的相同实现.
事实上,documentation的DynArraySetLength提供了SetLength作为多维数组的替代.也可以使用DynArraySetLength而不是类型转换,但是我没有看到任何理由喜欢一个或另一个.