0
votes

Say that I have the following record:

   type
     TTest = record
       test1 : TTest1;
       test2 : TTest2;
       test3 : TTest3;
   end;
   pTTest = ^TTest;
   TDictestDictionary = TDictionary<integer,pTTest>;
    testDictionary : TDictestDictionary 

Will it be sufficient to write

   testDictionary := TDictionary<integer,pTTest>.Create;

and then add the items like:

   testDictionary.AddOrSetValue(1,pValue);

or need to initialize pValue ?

But then what happens when:

   GetMem(pValue, Value);
   testDictionary.AddOrSetValue(1,pValue);
   FreeMem(pValue);

will the items remove the data pointed by pValue ?

Please Help

Also, on the same line of thought, can I have something like this:

Type
  myClass = class(TObject)

  private
    FTest : TDictestDictionary ;

 public 
   property propFTest : TDictestDictionary  read getFTest() write setFTest()

but then how I write getFTest() setFTest()

Help. Thank you

2
But why on Earth do you want to store the pointers?Jens Borrisholt
@Jens, because making a copy of the records might be wasteful and difficult to maintain ? Imagine that you can store the records in a plain array and make as much views as you want by using pointers. Yes, you must keep them in synch with those views, but you would have to do it for views having record copies as well.TLama
@JensBorrisholt without pointers code like testDictionary[1].test1 = ... will create copy of record and will not affect value in dictionary. In such cases you need to store record pointersteran
Ofcause then whay not use a class and TObjectDictionary. That makes memory management easier, and gives you the power of pointers.Jens Borrisholt

2 Answers

2
votes

If you really want to store pointers in your container, then you will need to allocate the memory at some point. If you deallocate the memory when the container still contains a reference to that memory, then the container's reference is useless. It is known as a stale pointer. Invariably, holding stale pointers means your code is defective.

There seems to me to be no need to use pointers here. You can declare the dictionary like this:

TDictionary<Integer, TTest>

That container holds copies of your records, and so manages the lifetime automatically.

0
votes

I would agree David. I see no need for pointers here. Use a class and a TObjectDictionary then you can create as many views as you want and memory management is still easy: One TObjectDictionary owns the classes the other TObjectDictionary or TList<>are just views presending your data different.

Here is a unit ment for inspiration.

unit TestDictionaryU;

interface

uses
  System.Generics.Collections;

type
  TTest1 = class
  end;

  TTest2 = class
  end;

  TTest3 = class
  end;

  TTest = class
    test1: TTest1;
    test2: TTest2;
    test3: TTest3;
    constructor Create;
    destructor Destroy; override;
  end;

  TTestDictonary = class(TObjectDictionary<Integer, TTest>)
  public
    constructor Create;
    function AddTest : TTest;
  end;

implementation

{ TTest }

constructor TTest.Create;
begin
  inherited;
  test1 := TTest1.Create;
  test2 := TTest2.Create;
  test3 := TTest3.Create
end;

destructor TTest.Destroy;
begin
  test1.Free;
  test2.Free;
  test3.Free;
  inherited;
end;

{ TTestDictonary }

function TTestDictonary.AddTest: TTest;
begin
  Result := TTest.Create;
end;

constructor TTestDictonary.Create;
begin
  inherited Create([doOwnsValues]);
end;

end.