如何获取泛型实例的Pointer指针?两种取指针方式为何不同?
泛型变量指针获取问题解答
示例Pascal代码
TTestClass = class content: Integer; end; TTest = class public class procedure TestProc<T: class>(obj: T); end; class procedure TTest.TestProc<T>(obj: T); var p: Pointer; begin p := Pointer(obj); p := @obj; end;
问题解析与解答
两种指针获取方式的差异原因
p := Pointer(obj)
当泛型约束为<T: class>时,T属于引用类型,obj本质是一个存储对象实例地址的指针。直接将obj转换为Pointer,得到的是堆内存中对象实例的实际地址——也就是这个引用指向的真实数据所在位置。p := @obj@运算符的作用是获取变量自身的内存地址。obj作为函数参数,存储在栈内存中(对于引用类型,这个栈变量里存的是对象实例的地址),因此@obj得到的是栈上这个参数变量的地址,和它指向的对象实例地址完全是两个不同的内存位置。
移除<T: class>约束后的通用指针获取方案
当T可以是任意类型(值类型如Integer、自定义记录,或引用类型如类、接口)时,需根据需求选择对应的指针获取方式:
场景1:获取变量自身的内存地址
无论T是值类型还是引用类型,直接使用@obj或Addr(obj)即可,两者效果一致。返回的指针指向存储obj这个变量的内存位置:
- 对于值类型,该地址指向栈上的变量副本;
- 对于引用类型,该地址指向栈上存储对象引用的变量。
场景2:获取变量对应实际数据的地址
需要区分T的类型,结合RTTI实现通用逻辑:
uses System.Rtti; class procedure TTest.TestProc<T>(obj: T); var p: Pointer; ctx: TRttiContext; typeInfo: TRttiType; begin typeInfo := ctx.GetType(TypeInfo(T)); if typeInfo.IsInstance then // 处理引用类型(类、接口等) p := Pointer(obj) else // 处理值类型 p := @obj; end;
内容的提问来源于stack exchange,提问作者John John
相关产品推荐
相关产品推荐

