Delphi如何让本地数组变量条件指向开放数组参数并解决E2010错误
问题根源
- Delphi中函数参数里的
const AValuesA: array of T属于开放数组参数,和本地声明的TArray<T>动态数组是完全不同的类型。开放数组参数仅携带元素首地址、长度两个信息,没有动态数组的引用计数、内存管理头结构,所以不能直接赋值给动态数组变量。 - 取地址赋值的写法属于强制语法绕过,但开放数组参数的地址并不是动态数组的头指针,访问时会直接越界触发访问违例,完全不安全,绝对不能使用。
最优解决方案
直接修改函数的参数类型为TArray<T>,Delphi的泛型动态数组兼容普通动态数组、静态数组作为输入参数,不需要修改上层调用逻辑,同时完全避免类型不兼容问题,还能满足你“直接指向参数避免额外拷贝”的原始需求。
修正后的核心代码:
type TArray = class(System.Generics.Collections.TArray) public // 仅需把参数的array of T改成TArray<T>即可 class function SameValues<T>(const AValuesA: TArray<T>; const AValuesB: TArray<T>; const AComparer: IEqualityComparer<T>; AOrderMatters : Boolean = True) : Boolean; overload; static; end;
修改参数后你原有的函数实现逻辑无需任何调整,ArrA := AValuesA这类赋值可以正常编译运行,是引用拷贝没有额外性能开销。
兼容旧代码的备选方案
如果因为兼容历史代码的原因不能修改参数类型,那不管顺序是否相关,统一将开放数组拷贝到本地动态数组即可,修改后的逻辑如下:
if(AOrderMatters) then begin // 开放数组无法直接引用,统一拷贝 SetLength(ArrA, Length(AValuesA)); TArray.Copy<T>(AValuesA, ArrA, Length(AValuesA)); SetLength(ArrB, Length(AValuesB)); TArray.Copy<T>(AValuesB, ArrB, Length(AValuesB)); end else begin // 原有拷贝排序逻辑不变 SetLength(ArrA, Length(AValuesA)); TArray.Copy<T>(AValuesA, ArrA, Length(AValuesA)); SetLength(ArrB, Length(AValuesB)); TArray.Copy<T>(AValuesB, ArrB, Length(AValuesB)); TArray.Sort<T>(ArrA); TArray.Sort<T>(ArrB); end;
该方案兼容性最好,缺点是顺序相关的场景也会多一次数组拷贝,性能略低于最优方案。
内容的提问来源于stack exchange,提问作者Fabrizio
相关产品推荐
相关产品推荐

