Board index » delphi » Why Object References?

Why Object References?

Can anyone explain why I would use Object References?  
(ie. ObjectRef: class of TObject)  Anything's got to be better than the Object
Pascal Reference (book).

If I have:

type
 TItem = class(TObject)
 end;

 TListOfItems = class(TList);
   public
     function GetCurrent : TItem;
   private
    iCurrent: integer;
 end;

function TListOfItems.GetCurrent : TItem;
var
 oItem: TItem;
begin
 oItem := TItem(Items[iCurrent]);
 GetCurrent := oItem;
end;

Would OR help in this instance (to take care of memory issues) or is something
else more appropriate?

I'm in the process of tracking down some memory stompin' and need to know
if Object References would help.

Richard Knapp

 

Re:Why Object References?


Quote
Richard Knapp wrote:

> If I have:

> type
>  TItem = class(TObject)
>  end;

>  TListOfItems = class(TList);
>    public
>      function GetCurrent : TItem;
>    private
>     iCurrent: integer;
>  end;

> function TListOfItems.GetCurrent : TItem;
> var
>  oItem: TItem;
> begin
>  oItem := TItem(Items[iCurrent]);
>  GetCurrent := oItem;
> end;

> Would OR help in this instance (to take care of memory issues) or is something
> else more appropriate?

> I'm in the process of tracking down some memory stompin' and need to know
> if Object References would help.

> Richard Knapp

The example you give is using Object References anyway.  Any variable of a type
derived from TObject is an Object Reference - effectively a pointer to an object (but
don't let anyone hear you suggest this - pointers in Delphi is a sensitive subject).
This is why the following code does not work:

    var
       ListBox: TListBox ;

    begin
       ListBox.Items.Add('Some Item') ;
        :
    end ;

ListBox is only a reference to an object - a reference which has not been resolved in
this code extract.  To make ListBox into a valid reference you would need:

   ListBox := TListBox.Create(FormObject) ;
or
   ListBox := SomeListBoxObjectFromElsewhere ;

Before you attempt to access the object that ListBox refers to.

I am guessing that your memory loss is being caused by objects not being freed by
your application.  Does your memory seem to reappear when your app terminates
(objects should be automatically freed by Delphi garbage collection upon termination)
or does your amnesia (memory loss - geddit?) persist even after your app has closed
down?

BTW: Might I suggest the following 'optimisation' (less typing) :-) for the function
in your example:

  function TListOfItems.GetCurrent : TItem;
  begin
    Result := TItem(Items[iCurrent]);
  end;

All functions have a variable implicitly defined called 'Result' which is of the same
type as the function return type.

I hope this helps,

--
Jolyon Smith                         |  The views represented above are my own
Application Development Consultant   |  and do not necessarily represent the
PLATINUM Solutions (UK)              |  views of my employer.

Re:Why Object References?


Quote
>The example you give is using Object References anyway.  Any variable of a type
>derived from TObject is an Object Reference - effectively a pointer to an object (but
>don't let anyone hear you suggest this - pointers in Delphi is a sensitive subject).

Oh, I spent some time digging through what little there is on this subject.  The
Object Reference (class of TObject) is intended to serve as a 'metaclass' for this
class.  Hmm.  That's a capability C++ does not currently have, although it can be
achieved with static members.

Richard

Re:Why Object References?


In <31C7CAD9.5...@platinum.com>, Jolyon Smith <sm...@platinum.com> writes:

Quote
>Richard Knapp wrote:

>The example you give is using Object References anyway.  Any variable of a type
>derived from TObject is an Object Reference - effectively a pointer to an object (but
>don't let anyone hear you suggest this - pointers in Delphi is a sensitive subject).
>This is why the following code does not work:

Yep.  I thought about that, too.

Quote
>I am guessing that your memory loss is being caused by objects not being freed by
>your application.  Does your memory seem to reappear when your app terminates
>(objects should be automatically freed by Delphi garbage collection upon termination)
>or does your amnesia (memory loss - geddit?) persist even after your app has closed
>down?

Actually, yes.  What I had was basically an assert when I tried to get the current
item.  If it was outside the normal boundary (0 < iItem < Count - 1) then report
a critical error and Halt.  That part worked.  What I wasn't doing was resetting the
current item index (iItem) when I reloaded the list.

In an effort to help track down the problem, I also 'nil'ed out all reference when
a function was returning.  ie.

function TList.GetItem : TItem;
var
  oItem: TItem;
begin
  oItem := Items[iCurrentItem];
  [code]
  GetItem := oItem;
  oItem := nil;
end;

I've seen this have an effect under TP 6 as far as the procedure/function trying
to destroy the item and figured it would not hurt to add some insurance ;-)

Quote
>BTW: Might I suggest the following 'optimisation' (less typing) :-) for the function
>in your example:

Okay.  Actually, there is more code in there.

Quote
>All functions have a variable implicitly defined called 'Result' which is of the same
>type as the function return type.

That's a new one to me.  It thought the return was always from the function name.
I'll have to get back in the books.... again!

Thanks!

Richard

Re:Why Object References?


In article <4qbm55$...@news.internetmci.com>, Richard Knapp
<74133.2...@compuserve.com> writes

Quote
>In <31C7CAD9.5...@platinum.com>, Jolyon Smith <sm...@platinum.com> writes:
>>Richard Knapp wrote:

>>The example you give is using Object References anyway.  Any variable of a type
>>derived from TObject is an Object Reference - effectively a pointer to an
>object (but
>>don't let anyone hear you suggest this - pointers in Delphi is a sensitive
>subject).
>>This is why the following code does not work:

>Yep.  I thought about that, too.

>>I am guessing that your memory loss is being caused by objects not being freed
>by
>>your application.  Does your memory seem to reappear when your app terminates
>>(objects should be automatically freed by Delphi garbage collection upon
>termination)
>>or does your amnesia (memory loss - geddit?) persist even after your app has
>closed
>>down?

>Actually, yes.  What I had was basically an assert when I tried to get the
>current
>item.  If it was outside the normal boundary (0 < iItem < Count - 1) then report
>a critical error and Halt.  That part worked.  What I wasn't doing was resetting
>the
>current item index (iItem) when I reloaded the list.

>In an effort to help track down the problem, I also 'nil'ed out all reference
>when
>a function was returning.  ie.

>function TList.GetItem : TItem;
>var
>  oItem: TItem;
>begin
>  oItem := Items[iCurrentItem];
>  [code]
>  GetItem := oItem;
>  oItem := nil;
>end;

Just to emphasise what Joylon smith said, when you create an item of
tobject in a procedure, the procedure or function will simply destroy
the 4 byte object reference, not the actual object.  This can be a pain
when working with some components.

When placing an object into a listboxes objects, freeing the object
screws it up.  Does the listboxe use assign?  probably not as this is
tpersistent hence, leaving the object reference after inserting it into
a TListobx for instance *is* valid:

procedure Tform1.MyList;
var
  MyObject: TMyObject;

begin
  MyObject := TMyObject.Create (Self);
  MyListBox.Items.AddObject ('Item', MyObject);
  MyObject := Nil;
end;

When the MyObject is created its data is placed somewhere and the
MyObject is the reference to that object data.  When the proc. ends the
4 byte pointer (ouch!) is destroyed, but not where it points to (ouch
ouch!).  Th listbox *should* destroy the memory pointed to by the
reference in its object list.

I hope David isn;t watching...
--
Nicholas Robinson

Re:Why Object References?


Quote
>Just to emphasise what Joylon smith said, when you create an item of
>tobject in a procedure, the procedure or function will simply destroy

I understand that point.  This is not a problem.  That is correct according to the
scope rules.

Quote
>When placing an object into a listboxes objects, freeing the object
>screws it up.  Does the listboxe use assign?  probably not as this is
>tpersistent hence, leaving the object reference after inserting it into
>a TListobx for instance *is* valid:

>procedure Tform1.MyList;
>var
>  MyObject: TMyObject;

>begin
>  MyObject := TMyObject.Create (Self);
>  MyListBox.Items.AddObject ('Item', MyObject);
>  MyObject := Nil;
>end;

>When the MyObject is created its data is placed somewhere and the
>MyObject is the reference to that object data.  When the proc. ends the
>4 byte pointer (ouch!) is destroyed, but not where it points to (ouch
>ouch!).  Th listbox *should* destroy the memory pointed to by the
>reference in its object list.

Why is this a problem?  This is what it should do.  The reference is local to
this procedure.  If you call the Free method of a list, it will call the destructor
for each item in the list ( or it should) through the Free method.

Now, on to the rest of the question.  Does an Object Reference substitute as
a meta-class?

Richard Knapp

Re:Why Object References?


Quote
Richard Knapp wrote:

> In an effort to help track down the problem, I also 'nil'ed out all reference when
> a function was returning.  ie.

> function TList.GetItem : TItem;
> var
>   oItem: TItem;
> begin
>   oItem := Items[iCurrentItem];
>   [code]
>   GetItem := oItem;
>   oItem := nil;
> end;

> {snip}

> Thanks!

Glad I could be of help.

Just one more thing tho'.  In your code clip, 'oItem' ceases to exist when your function
returns - the object it refers to however, does not - NIL'ing the reference does nothing to
the object apart from dissasociate it from 'oItem'.

I would expect the optimiser to remove this (but have not checked) since the variable is then
disposed of, but in months/years to come you may get confused when you come across this...

Just a thought.

--
Jolyon Smith                         |  The views represented above are my own
Application Development Consultant   |  and do not necessarily represent the
PLATINUM Solutions (UK)              |  views of my employer.

Re:Why Object References?


In <31D008AC.4...@platinum.com>, Jolyon Smith <sm...@platinum.com> writes:

Quote
>Richard Knapp wrote:

>> In an effort to help track down the problem, I also 'nil'ed out all reference when
>> a function was returning.  ie.

>> function TList.GetItem : TItem;
>> var
>>   oItem: TItem;
>> begin
>>   oItem := Items[iCurrentItem];
>>   [code]
>>   GetItem := oItem;
>>   oItem := nil;
>> end;

>> {snip}

>> Thanks!

>Glad I could be of help.

>Just one more thing tho'.  In your code clip, 'oItem' ceases to exist when your function
>returns - the object it refers to however, does not - NIL'ing the reference does nothing to
>the object apart from dissasociate it from 'oItem'.

>I would expect the optimiser to remove this (but have not checked) since the variable is then
>disposed of, but in months/years to come you may get confused when you come across this...

Actually, I wanted to specifically prevent the original item from being destroyed.
I just want to access the current item.  I remember having trouble under TP 6 with
pointers/refs if I did not set the reference to nil (since it tried to delete the actual
item) and added that 'catch' here.

Thanks again.

Richard

Other Threads