ROOT Version: root/6.12.06 Platform: Red Hat Enterprise Linux Server release 7.6 (Maipo) Compiler: gcc/6.2.0
Is there a correct way to create a std::unique_ptr to a TTree in a TFile?
I am used to doing:
TFile* file = new TFile("name.root", "READ");
TTree* tree = (TTree*) file->Get("name");
but would like to start using std::unique_ptr, so I tried:
auto file = std::unique_ptr<TFile> {TFile::Open("name.root", "READ")};
auto tree = std::unique_ptr<TTree> {file->Get("name")}; // this does not work!
This does not compile with ACLiC. The first error message is:
error: no matching constructor for initialization of 'std::unique_ptr<TTree>'
Is there a correct way to do this? Is there anything I should be aware of (any “gotchas” in terms of ROOT’s memory management)? Also, please let me know if there is a better way to create a std::unique_ptr to a TFile (the first line in my example).
Hi,
to make it compile, you just need to cast the TObject* returned by TFile::Get to a TTree*.
Or you can use the TFile::GetObject variant to get a TTree* directly.
But you will have to be very careful with the lifetimes of those file and tree pointers: TFile owns the objects extracted from it, so:
if file goes out of scope before tree, it will delete the TTree object, then tree's destructor will also delete the TTree object (like a good unique_ptr does) and you will get a crash
if tree goes out of scope before file, the TTree destructor will inform its TFile and deregister from it, so everything is fine
Another solution is to use unique_ptr for the TFile (guarantees no TFile leaks) and use a raw TTree* pointer for the TTree, with the modern C++ meaning of non-owning pointer, leaving it up to the TFile destructor to delete the TTree object.
Hope this is more clarifying than it is confusing
Cheers,
Enrico
Thanks for your help! I think I will follow your suggestion of creating a raw pointer to the TTree. In that case I will simply do:
auto file = std::unique_ptr<TFile> {TFile::Open("name.root", "READ")};
auto tree = (TTree*) file->Get("name");
Out of curiosity though, I would like to learn how to create the std::unique_ptr to the TTree in my example. Would you please provide the correct syntax? I tried:
auto tree = (std::unique_ptr<TTree>) file->Get("evtTree");
which yields this error:
error: no matching conversion for C-style cast from 'TObject *' to 'std::unique_ptr<TTree>'