2011-11-07 90 views
8

我一直覺得Delphi中的對象實際上是對內存位置的引用,而我想象的內存位置則是作爲指針變量存儲的。爲什麼TValue.Make需要一個指向對象引用的指針?

現在,我想從一個對象中製作TValue。考慮到這一點:

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

其中val: TValue。這不起作用。事實上,隨後使用val將導致訪問衝突。但是,如果我們使用地址運算符,如下所示:

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

一切都很好。對我而言,這是意想不到的,因爲我認爲AObject實際上是一個指針。我錯了,還是這是一個與TValue.Make方法的怪癖?有人請賜教嗎?

回答

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期望的是哪一種類型的指針。

+0

非常感謝和簡潔的解釋! – conciliator

+0

微妙而基本的...... ;-) +1 –

1

在您的示例中,AObject是對對象的引用,而不是對象本身。這是在Delphi中聲明對象引用的方式,而不是其他語言,在這種語言中,您必須明確地向對象添加引用或指針。

所以AObject@AObject應該工作一樣在你的情況,但作爲TValue.Make()需要一個指向第一個參數一個緩衝區,你應該提供Addr(AObject)@AObject的功能。

+1

但是@conciliator聲明'AObject'和'@ AObject'對他的工作方式不同,它似乎與您的答案相矛盾? – Zruty

+0

@TridentT:我必須承認我還是很困惑。如果'AObject'和'@ AObject'都是指針,爲什麼一個工作而不是另一個?直覺上,我認爲'@ AObject'是指向指針的指針。 (例如,假設我想從一個int intvar'中創建一個TValue,在這種情況下,'@ intvar'非常合理,但目標案例仍然讓我感到困惑......) – conciliator

2

傳遞給TValue.Make的ABuffer參數是指向要存儲在TValue內的值的指針。如果類型本身是指針類型,則無關緊要。所以即使AObject本身也是一個指針,你必須將引用傳遞給AObject。

在這個例子中,你貼我寧願使用TValue.From <牛逼>方法:

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

如果所屬類別並不在編譯時知道你必須使用TValue.Make - 否則TValue.From <T>更易於使用。

相關問題