Ownership of TFitResult returned by TGraph

Hi, I read the “Object ownership” section of the ROOT users guide, and it says:

I’m using TGraph::Fit, which returns a TFitResultPtr holding (but, by reading the destructor code, not owning) a pointer to a TFitResult. I’m wondering if I own the TFitResult. I have this concern because I’m fitting in a cycle, now I’m doing something like

TGraph graph(...);
unique_ptr<TFitResult> fit {&*graph.Fit(...)};

I assumed to own it because it makes sense: otherwise a TGraph would have to store a vector of TFitResults just to delete the arbitrarily many fit results generated.

Update: using the above code

results in segmentation faults, while

TFitResultPtr = graph.Fit()

i.e. storing the TFitResultPtr on the stack does not, so the object is in some way owned and deleted by ROOT. I thought not because the destructor of TFitResultPtr is

/// Destructor. Delete the contained TFitResult pointer if needed
///     if ( fPointer != 0)
///       delete fPointer;


where fPointer is a std::shared_ptr, so should not be automatically deleted in any way.

Hello @gipetril

it’s explained in the documentation, specifically the section about the TFitResult:

If the option “S” is instead used, TFitResultPtr contains the TFitResult and behaves as a smart pointer to it.

Note, in particular, that the TFitResultPtr is an object and not a pointer, in the same way that a unique_ptr is not a pointer (that you can e.g. delete). You should not wrap it in anything, but just keep it on the stack.

“Behaves as a smart pointer” is not clear to me on the policy for deleting the object. Since in the code TFitResultPtr does not contain a TFitResult but a std::shared_ptr<TFitResult>, i.e. a pointer handler which does not call delete on its pointer upon destruction, and ~TFitResultPtr is defined explicitly to do nothing, it is not obvious that I do not have to delete the pointer contained in the TFitResultPtr, provided I do not trust that section of the manual because in this case it appears more efficient to relinquish property of the TFitResult to the user.

Anyway, as I said, I was wrong, and I don’t have to delete &*result_ptr.

I was wrapping the TFitResult, not the TFitResultPtr.

EDIT: I was wrong, shared_ptr does delete its pointer.

This means that the TFitResultPtr will take care of deleting the FitResult it points to. In that sense, it behaves like std::unique_ptr and std::shared_ptr. (As you saw yourself, it is actually implemented using a shared_ptr, so all is taken care of.)

Do you think that the documentation of the TFitResultPtr needs to be improved?

Sorry, I said this:

which is actually completely false, shared_ptr does delete its pointer.

Well, since I got it so wrong, I would say yes.