【问题标题】:Why does TValue.Make require a pointer to an object reference?为什么 TValue.Make 需要指向对象引用的指针?
【发布时间】:2011-11-07 10:07:38
【问题描述】:

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

现在,我想从一个对象中创建一个 TValue。考虑一下:

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

在哪里val: TValue。这行不通。事实上,后续使用val 会导致访问冲突。但是,如果我们使用 address-of 运算符,如下所示:

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

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

【问题讨论】:

    标签: delphi object pointers


    【解决方案1】:
    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 方法:

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

    如果在编译时不知道类型信息,则必须使用 TValue.Make - 否则 TValue.From 更易于使用。

    【讨论】:

      【解决方案3】:

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

      所以 AObject@AObject 在您的情况下应该工作相同,但由于 TValue.Make() 在第一个参数中采用指向缓冲区的指针,您应该提供 @ 987654322@ 或 @AObject 到函数。

      【讨论】:

      • 但是@conciliator 指出AObject@AObject 对他的工作方式不同,这似乎与您的答案相矛盾?
      • @TridentT:我不得不承认我仍然很困惑。如果AObject@AObject 都是指针,为什么一个工作而不另一个工作?直观地说,我认为@AObject 是指向指针的指针。 (例如,假设我想从一个 int intvar 生成一个 TValue。在这种情况下,@intvar 非常有意义,但对象情况仍然让我感到困惑......)
      猜你喜欢
      • 2014-01-26
      • 1970-01-01
      • 2010-10-28
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多