Static TClonesArray in Event class

Dear rooters,

the Event class defined in ROOT/test directory has a static member variable called fgTracks pointing to a TClonesArray. I guess it is used to get back the lost memory allocated in the Event ctor (though I am always puzzled why it is lost…).

Does it mean that only one instance of Event class can be used? Otherwise the same TClonesArray will be shared by more than one instance of Event class. Do I get something wrong?

Cheers, Jing

Hi Jing,

You are correct. The reason to use a static TClonesArray in this case is to save on the time/cost of allocating/dealllocating the array and its elements when you allocated/deallocate the Event object.

Cheers,
Philippe.

Dear Philippe,

thank you for your quick reply. Meanwhile, I found an old post concerning the same issue:

root.cern.ch/root/roottalk/roottalk03/2779.html

But there is no concrete conclusion.

It sounds like, if there is no obvious problem, you can allocate memory in your constructor. I actually found through google in a famous experiment they do create several TClonesArray objecs in a constructor (They put a FIXME in the comment though).

If I do want to create several Event instances and still use TClonesArray, what’s your suggestion?

Thanks a lot,

Cheers, Jing

Hi,

[quote]If I do want to create several Event instances and still use TClonesArray, what’s your suggestion? [/quote]Then I recommend that you remove the static TClonesArray and keep on pointer to TClonesArray in the Event class and you can allocates the TClonesArray either in the default constructor of Event or the first time you add a Track to the array (in which case the default constructor ought to set the pointer to zero).

Cheers,
Philippe.

PS. Of course do not forget to delete the TClonesArray in the destructor.

Dear Philippe,

thank you! The thing that makes me hesitate to do what you suggested is the following sentence I read in the section “The Default Constructor” in the ROOT Documentation “Adding a Class”:

if you allocate memory in the default constructor, “The memory will be lost because during reading of the object the pointer will be set to the object it was pointing to at the time the object was written.”

This is hard for me to understand. Could you please say something more about it? Is it just a warning that there might be cases where the memory is leaked or is it a strict rule that there is certainly a memory leak if you do so?

I understand that a static TClonesArray will save time/cost when I allocate/deallocate Event because it is independent from any Event instance. But in this case, shouldn’t Event be made a singleton? So that users cannot create two Event instances and mess up the memory.

Cheers, Jing

[quote]if you allocate memory in the default constructor, “The memory will be lost because during reading of the object the pointer will be set to the object it was pointing to at the time the object was written.”[/quote]Gladfully this statement is obsolete and the memory will indeed not be lost (but will be ‘wasted’ as the object your constructed in the default constructor will be deleted and recreated by the Streamer during reading).

Note that you can even alleviate this by using the -> annotation:class Event { ... TClonesArray *fTrack; //-> };The ‘->’ tells root that
[ul]- fTrack is always allocated during the default constructor

  • type type of the object pointer to by fTrack is always TClonesArrays[/ul]

[quote]I understand that a static TClonesArray will save time/cost when I allocate/deallocate Event because it is independent from any Event instance. But in this case, shouldn’t Event be made a singleton? So that users cannot create two Event instances and mess up the memory.
[/quote]Indeed the Event class should be a singleton in our example.

Cheers,
Philippe.[/quote]

Great! I will just follow your suggestion. Thank you so much!

By the way, if I use the following way to initialize Event

class Event
{
public:
   Event():fTracks("Track",1000) {};
   ...
private:
   TClonesArray fTracks;
   ...
};

I don’t need to delete the pointer in the d’tor. But is it as efficient as pointer with “//->”?

Cheers, Jing

Hi,

[quote]I don’t need to delete the pointer in the d’tor.[/quote]You are correct.

[quote]But is it as efficient as pointer with “//<-”? [/quote]The options are very similar.

Cheers,
Philippe.

Great. Thank you!