Сохранить адрес указателя в варианте и получить к нему доступ - PullRequest
1 голос
/ 10 мая 2011

У меня есть вопрос новичка с использованием указателей в 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 ]

3 голосов
/ 10 мая 2011

Я думаю, что ваша основная проблема связана с тем, что является ссылкой на объект 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 - забавный гибрид.Хотя они реализованы как ссылки, копирование при записи заставляет их вести себя как типы значений.

Синтаксис 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.

2 голосов
/ 10 мая 2011

Во-первых, вам действительно не нужен указатель на ваш объект, потому что сам объект уже является ссылочным типом, и вы можете привести свою ссылку на объект к integer (хотя NativeInt может быть лучше.) используя его, вы должны получить целое число обратно из варианта и привести его обратно к вашему типу указателя / объекта, например так:

var
  intref: NativeInt;
  cell: TsplCellObject;
begin
  intref := myvar;
  cell := TsplCellObject(intref);
  //do something with Cell here
end;
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...