Dear experts,
I am learning how to use smart pointers. I want to read a series of ROOT files and load histograms from each file – while managing the object ownership and memory allocation myself or with smart pointers.
Here is a snippet of my code, with questions in-line:
- According to [1], ROOT does not manage TFiles, so I do not need to set
m_File->AddDirectory(0)
. Correct? Here, I am constructing a TFile object on the heap with the default c’tor, with the file path forwarded to the constructor.m_File
is astd::shared_ptr
.
if (boost::filesystem::exists(inputFilePath)) {
m_File = std::make_shared<TFile>(inputFilePath.string().c_str()));
}
- The following snippet works. But I think it can be simplified by simply passing h directly into the copy constructor of
hclone
(which does aCopy()
). Is this preferred?
for (auto hn : histogramNames) {
for (auto p : processMap) {
std::shared_ptr<TFile> pfile = p.second.File(); // File() does return-by-value of m_File
if (pfile->GetListOfKeys()->Contains(hn.c_str())) {
TH1 *h;
pfile->GetObject(hn.c_str(), h);
std::shared_ptr<TH1D> hclone = std::make_shared<TH1D>(*(static_cast<TH1D*>(h->Clone())));
h->AddDirectory(0);
hclone->AddDirectory(0);
rank.emplace(h->Integral(), h); // emplace into multimap of <float, std::shared_ptr<TH1>>
}
}
TH1 *h;
pfile->GetObject(hn.c_str(), h);
std::shared_ptr<TH1D> hclone = std::make_shared<TH1D>(static_cast<TH1D>(h));
h->AddDirectory(0);
hclone->AddDirectory(0);
- Since I am managing the objects with smart pointers, I need to set
AddDirectory(0)
on bothh
andhclone
. SinceClone()
returns aTObject *
, I suspect that there is a memory allocation here that is not cleaned up if I choose to remove it fromgDirectory
. Is this correct?
(Histograms in different ROOT files share the same name and I can’t have TObjects with the same name in the same gDirectory
, so either I need to Clone("...")
with a unique string or set AddDirectory(0)
. This must be done regardless of using smart pointers or not…)
- If the histogram read in from the file,
h
, is a TH1I, it will turn into a TH1D because of the cast. This is not really efficient. How can I make this snippet of code more flexible? This does not work (TH1::TH1(const TH1&)’ is private within this context
):
std::shared_ptr<TH1> hclone = std::make_shared<TH1>(static_cast<TH1>(h));
- How does this work with THStacks and canvases? Is it safe to
Add(TH1 *h)
to a THStack, where everyh
inside the TList of the stack has the same name and whose ownership is not managed by ROOT?
Thanks,
Justin
[1] https://root.cern.ch/root/htmldoc/guides/users-guide/ObjectOwnership.html