保存变量中指针的地址并访问它

时间:2011-05-10 17:19:23

标签: delphi pointers

我有一个在delphi中使用指针的初学者问题。

我创建了一个对象并将其地址保存在变量变量中。 但我不知道如何使用此变量访问该对象。 这是我的代码:

...
      New(PSplObj);
      PSplObj^ := TsplCellObject.Create;
      PSplObj.description := sTeam;
      PSplObj.color := clRed;
      myvar := Integer(PSplObj);
      dispose(PSplObj);

      // how to access the object throug the pointer in myvar?
...

2 个答案:

答案 0 :(得分:3)

我认为您的主要问题与Delphi对象引用有关。请考虑以下人为举例:

type
  TMyRecord = record
    a, b, c: Integer;
  end;
  TMyClass = class
    a, b, c: Integer;
  end;
... 
var
  MyRecord: TMyRecord;
  MyObject: TMyObject;
...
MyObject := TMyObject.Create;

此时我们有两个基本相同的结构化类型的实例。然而,Delphi呈现这些实例的方式却截然不同。记录是所谓的值类型,对象是引用类型。

分配给引用类型的变量时,将复制该值。例如:

MyRecord2.a := 1;
MyRecord1 := MyRecord2;
MyRecord1.a := 2;
Assert(MyRecord1.a<>MyRecord2.a);

值类型的示例包括整数,枚举类型,浮点类型,记录,对象等。

相反,分配给引用类型变量会复制引用,以便两个变量引用同一个对象。例如:

MyObject2.a := 1;
MyObject1 := MyObject2;
MyObject1.a := 2;
Assert(MyObject1.a=MyObject2.a);

引用类型的一个特性是它们都是堆分配的,而值类型可以是堆或堆栈分配。

引用类型的示例包括类,接口,动态数组。

Delphi字符串是一个有趣的混合体。虽然它们是作为引用实现的,但是copy-on-write使它们的行为类似于值类型。

Delphi的对象语法隐藏了它们作为引用实现的事实,即指针。

Assert(SizeOf(MyRecord)=3*SizeOf(Integer));//=12
Assert(SizeOf(MyObject)=SizeOf(Pointer));//=4 (or 8 in Delphi 64)

这一切意味着您的代码不必要地复杂化。由于对象变量已经是引用,因此您无需为对象引用分配存储空间。你可以这样写:

//assign object reference to Variant
MyVariant := NativeInt(MyObject);

//extract object reference from Variant
NativeInt(MyObject) := MyVariant;

请注意,我使用NativeInt,因为它是一个整数类型,定义为至少与指针大小相同。当出现64位版本的Delphi时,这将变得相关。

答案 1 :(得分:2)

首先,你并不需要指向对象的指针,因为对象本身已经是一个引用类型,你可以将对象引用转换为integer(虽然NativeInt可能是更好。)要使用它,你必须从变量中取出整数并将其强制转换为指针/对象类型,如下所示:

var
  intref: NativeInt;
  cell: TsplCellObject;
begin
  intref := myvar;
  cell := TsplCellObject(intref);
  //do something with Cell here
end;