Re: ROOT collections

From: Fons Rademakers (Fons.Rademakers@cern.ch)
Date: Tue Oct 07 1997 - 18:34:17 MEST


Pasha Murat wrote:
> 
>         I have a couple of questions about ROOT arrays - after
>         looking over the documentation for quite a while I felt like
>         I still don't have all the answers.
> 
> - how does the TObjArray know the number of elements in it? It is smart:
>   it doesn't do compression when one of its objects is deleted therefore
>   it allows "holes" in its structure.
>   Does it mean that to get the number of objects in TObjArray one has to
>   calculate this number explicitly by iterating over the collection each time
>   he needs it?
>
The are two cases:
  - no holes: TObjArray::GetEntriesFast() returns number of objects in
    array. Note: this is <= size of array (returned by TObjArray::Capacity()
    or GetSize()).
  - holes: TObjArray::GetEntries() returns number of objects in array
    (done by looping over array, thus expensive).

In both cases GetLast() returns the index of the last occupied slot
in the array (slot <= size). To loop over the complete array do:

   for (int i = arr.LowerBound(); i < arr.GetLast(); i++)
      if (arr[i]) { ... }

By default LowerBound() is 0, so one can do:

   for (int i = 0; i < arr.GetLast(); i++)
      if (arr[i]) { ... }

Or use the standard TIter technique:

   TIter next(arr);
   TObject *obj;
   while (obj = next()) {
      ...
   }

The iterator steps over empty slots so not check for 0 object is needed.

> 
> - Is it possible to put an existing object into ROOT collection without
>   creating its clone on heap?
>   What happens if a locally defined object has been added to a collection?
>   Is it always necessary to use new?
>   If the answer to the previous quiestion is "yes", it means that collection
>   doesnt' own its objects in a sense that they've been created outside the
>   collection. So what happens then with the objects when collection gets
>   deleted? Who keeps the responsibility for deleting the objects?
> 

ROOT collections store pointers to TObjects. The pointer may point to a
heap based object or to a stack based (local) object. In the later case
one must take care to remove the object from the collection just before
the object goes out of scope (this can be done by the object dtor in
case the object knows in which collection it is stored).

A collection can be an "owning" collection. I.e. it will take care
of deleting the objects which pointers are stored in it. This is done
via TCollection::Delete(). In Delete() the collection is iterated and
every object is deleted (except for stack based objects, since they
will be deleted by the C++ run-time). The whole thing of "ownership"
is a matter of convention and not explicitely enforced. For example:

class Event : public TObject {
private:
   TList  *fTracks;
   TList  *fVertex1;
   TList  *fVertex2;
   ...
public:
   virtual ~Event() { if (fTracks) fTracks->Delete();
                      delete fTracks;
                      delete fVertex1;
                      delete fVertex2;
                    }
};

Assume that in the above class fTracks is an "owning" collection.
It owns the tracks stored in it (no other references to the tracks
are available). And fVertex1 and fVertex2 are lists containing a, 
possible overlapping, subset of tracks that belong to either of
the two vertex candidates. The two vertex track lists don't own
the objects stored in it. So in the Event dtor we have to call
fTracks->Delete() to delete all tracks. The TList dtors just
reclaim the TList data structure.

Cheers, Fons.

-- 
Org:    CERN, European Laboratory for Particle Physics.
Mail:   1211 Geneve 23, Switzerland          Phone: +41 22 7679248
E-Mail: Fons.Rademakers@cern.ch              Fax:   +41 22 7677910



This archive was generated by hypermail 2b29 : Tue Jan 04 2000 - 00:26:21 MET