为什么TValue.Make需要指向对象引用的指针?

时间:2011-11-07 10:07:38

标签: delphi object pointers

我一直认为Delphi中的对象实际上是对内存位置的引用,而我认为这些内存存储为指针变量。

现在,我想从一个物体制作一个TValue。考虑一下:

TValue.Make(AObject, TypeInfo(TMyObject), val);

其中val: TValue。这不行。实际上,后续使用val会导致访问冲突。但是,如果我们使用address-of运算符,就像这样:

TValue.Make(@AObject, TypeInfo(TMyObject), val);
一切都很好。对我来说,这是出乎意料的,因为我认为AObject(引擎盖下)实际上是一个指针。我错了,或者这是TValue.Make方法的怪癖?有人可以赐教我吗?

3 个答案:

答案 0 :(得分:9)

procedure Foo;
var
  I: Integer; // value type
  O: TObject; // reference type
begin
  @I; // Get a pointer to I
  O := TObject.Create;
  @O; // Get a pointer to the memory "behind" the reference O
end;
  • 位置@I以及O(引用)的位置在堆栈中。
  • 另一方面,@ O的位置在堆上。

通常这并不重要,因为编译器知道何时取消引用,何时不知道。

TValue.Make的情况下,该函数采用指针。

  • 当您指定Make(O...时,编译器将硬引用指针(指向堆栈)。
  • 当您指定Make(@O...时,编译器将首先取消引用,然后创建指向堆上位置的指针。

所以你必须在这种情况下给编译器一个提示,因为它不知道TValue.Make期望哪种指针。

答案 1 :(得分:2)

传递给TValue.Make的ABuffer参数是指向要存储在TValue中的值的指针。类型本身是否是指针类型并不重要。因此,即使AObject本身也是指针,您也必须将引用传递给AObject。

在您发布的示例中,我更倾向于使用TValue.From< T>方法:

val := TValue.From<TMyObject>(AObject);

如果在编译时不知道typeinfo,则必须使用TValue.Make - 否则TValue.From&lt; T&gt;更容易使用。

答案 2 :(得分:1)

在您的示例中,AObject是对对象的引用,而不是对象本身。这是在Delphi中声明对象引用的方法,而不是必须显式添加对象的引用或指针的其他语言。

所以 AObject @AObject 应该在你的情况下工作相同,但是当TValue.Make()在第一个参数中取一个指向缓冲区的指针时,你应该向该函数提供Addr(AObject)@AObject