I was looking into the code of TClonesArray::Remove
and TClonesArray::RemoveAt
in comparison to the TObjArray
implementation. This was somewhat confusing to me. (I will come to my use case later on.)
- Let’s call
Remove
with an object that is findable. TClonesArray returns the object that was “used to search for”. TObjArray returns the “found” object. These can be different, if theIsEqual
member function has been overridden (which is the case for TObjString). - Let’s
RemoveAt
an object that exists. TObjArray returns the removed object. TCloneArray always returnsnullptr
. - Now let’s look at object lifecycle… TObjArray always returns objects in their current (usually fully contructed / etc) state. TClonesArray::Remove returns a pointer to a destructed object. So accessing anything there is probably UB. The pointer can only be used as a “Well, there was something” indicator. Like a
bool
. - Now let’s look at ownership. If TObjArray owns its contents (
SetOwner
), then Remove / RemoveAt can be used to “extract” / “release” (unique-ptr naming) the object and acquire ownership. For TClonesArray (which always owns its contents) this is not possible (see also TClonesArray not owner?)
TClonesArray derives from TObjArray. So one can use TClonesArray in place of a TObjArray. But Remove / RemoveAt have quite different semantics. This is at least surprising.
My use case is basically the last point / the point of the linked (quite old) thread. I would like to acquire ownership of one (or multtiple) objects from a TClonesArray. The only option that I have found by now: Have a separate TClonesArray, and use TClonesArray::AbsorbObjects
to move the single object over. The separate TClonesArray will function as an owner for one single object than.
ROOT Version: latest