Почему TValue.Make требует указатель на ссылку на объект? - PullRequest
8 голосов
/ 07 ноября 2011

У меня всегда было впечатление, что объекты в Delphi на самом деле являются ссылками на области памяти, которые, в свою очередь, я себе представлял, были сохранены как переменные-указатели.

Теперь я хочу сделать TValue из объекта. Учтите это:

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

, где val: TValue. Это не сработает. Фактически, последующее использование val приведет к нарушению доступа. Однако, если мы используем адрес оператора, например, так:

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

все хорошо. Для меня это было неожиданно, так как я думал, что AObject был (под капотом) фактически указателем. Я ошибаюсь или это причуды с методом TValue.Make? Может ли кто-нибудь, пожалуйста, просветить меня?

Ответы [ 3 ]

9 голосов
/ 07 ноября 2011
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.

2 голосов
/ 30 мая 2012

Аргумент ABuffer, который вы передаете TValue. Make - указатель на значение, которое вы хотите сохранить внутри TValue. Неважно, является ли сам тип указателем или нет. Таким образом, вы должны передать ссылку на AObject, даже если сам AObject также является указателем.

В приведенном вами примере я бы предпочел использовать метод TValue.From :

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

Если typeinfo неизвестна во время компиляции, вы должны использовать TValue.Make - иначе TValue.From проще в использовании.

1 голос
/ 07 ноября 2011

В вашем примере AObject - это ссылка на объект, а не сам объект. Это способ объявления ссылки на объект в Delphi в отличие от других языков, где вы должны явно добавить ссылку или указатель на объект.

То есть AObject или @ AObject в вашем случае должно работать так же, но, поскольку TValue.Make() принимает указатель на буфер в первом параметре, вы должны указать Addr(AObject) или @AObject к функции.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...