Jump to content
Dave Novo

How to get pointer to record at the top of TStack<T>

Recommended Posts

I have a section of code where I need to modify the top record on a stack. This code is supposed to be highly performant, so I would like to optimize it as much as possible. I would like to get the top record of the stack without popping and pushing it. The record is somewhat complex, so copying the data back and forth to a temporary record is silly. A sample program is below

 

type
  TMyRec=record
    s:string;
  end;
 
  PMyRec=^TMyrec;
 
var
  stk:TStack<TMyRec>;
  rec:TMyRec;
  prec:pMyRec;
begin
  stk:=TStack<TMyRec>.Create;
  rec.s:='Hello';
  stk.push(rec);
  prec:=@stk.Peek; // get error “variable required”
  prec.s:=’Goodbye’;
  stk.Free;
end;

 

Seems like @stk.Peek is returning the address to the Peek method, not the pointer of the element being returned by the peek method.  I have tried casting in various ways but it never compiles properly. Any ideas?

Share this post


Link to post
Posted (edited)

"@" operator requires a variable/constant/..., 

Here is your way :

type

  PMyRec = ^TMyRec;

  TMyRec = record
    s: string;
  public
    function Address(): PMyRec; inline;
  end;

var
  stk: TStack<TMyRec>;
  rec: TMyRec;
  prec: PMyRec;

  { TMyRec }

function TMyRec.Address: PMyRec;
begin
  Result := @Self;
end;

begin
  stk := TStack<TMyRec>.Create;
  rec.s := 'Hello';
  stk.push(rec);
  prec := stk.Peek().Address();
  Writeln(prec.s);
  prec.s := 'Goodbye';
  stk.Free;
end.

 

Edited by Mahdi Safsafi
  • Like 1

Share this post


Link to post

Surely that's just going to copy the record to a temp local, and return the address of that temp local. Or am I missing something? 

Share this post


Link to post
22 minutes ago, David Heffernan said:

Surely that's just going to copy the record to a temp local, and return the address of that temp local. Or am I missing something? 

Yes that's right.

Share this post


Link to post
Posted (edited)
12 minutes ago, Mahdi Safsafi said:

@Dave Novo As David pointed out,  you may need to use @stk.List[xxx].

"may" is rather weak. A more detailed clarification may be useful to the asker, to make it clear that the code you offered does not prevent a copy, and in fact just adds obfuscation. 

 

However, it's also possible that there is premature optimisation going on here. 

Edited by David Heffernan

Share this post


Link to post
3 minutes ago, David Heffernan said:

"may" is rather weak. A more detailed clarification may be useful to the asker, to make it clear that the code you offered does not prevent a copy, and in fact just adds obfuscation. 

 

However, it's also possible that there is premature optimisation going on here. 

He wrote "@stk.Peek" and I understood that he wanted the address of the peeked value. 

Share this post


Link to post
4 minutes ago, David Heffernan said:

What value of xxx is to be used? 

Hmmm that depends on him e.g  : stk.count - 1 ; 0 ; 1 ....

Share this post


Link to post
17 minutes ago, Mahdi Safsafi said:

He wrote "@stk.Peek" and I understood that he wanted the address of the peeked value. 

No. It's clear. He wants the address of the record stored internally by the class to avoid a copy. 

Share this post


Link to post

I wanted to modify the top record of the stack, without removing the record from the stack. Seems like with the way records work (copies all the time) that may not be possible with the current TStack implementation, given the intermediate records that are along the way. With our own structures, in situations that require it, we do take the effort to ensure there are no intermediate records and we get direct access to the address of the record we want to modify. I had not considered that the result of Peek would actually be a copy of the record at the top of the stack.

Share this post


Link to post
9 minutes ago, Dave Novo said:

I wanted to modify the top record of the stack, without removing the record from the stack. Seems like with the way records work (copies all the time) that may not be possible with the current TStack implementation, given the intermediate records that are along the way. With our own structures, in situations that require it, we do take the effort to ensure there are no intermediate records and we get direct access to the address of the record we want to modify. I had not considered that the result of Peek would actually be a copy of the record at the top of the stack.

My bad, I didn't understood you correctly. 

As I mentioned before, you can still use @stk.List[value] to get a pointer of your record without copying the data.

Share this post


Link to post

In Delphi Seattle, there is no List array property. The internal array is called FItems and it is Private.

Share this post


Link to post

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

×