Home | News | Documentation | Download

Copying a histogram in a function

Hello,

Is there a recommended or proper way to pass a histogram to a function, set it to a copy of an existing histogram and have it retain the info? Currently the histogram I pass is filled properly but lost when the function ends. Here’s a MWE demonstrating the issue:

MWE.C

void FillHist(TH1F* hist)
{
    TH1F* temp = new TH1F("h1","h1",10,0,1);
    temp->Fill(0.5);
    hist=(TH1F*)temp->Clone();
    cout<<hist->GetEntries()<<endl;
}
void MWE()
{
    TH1F* hist = new TH1F("h","h",10,0,1);
    FillHist(hist);
    cout<<hist->GetEntries()<<endl;
}

Output:

1
0

In the example the histogram “hist” will have 1 entry at the end of FillHist, however the print statement at the end of MWE() will print 0. I assume this is due to the scope of hist not extending past the function after the clone. Is there a better way to copy temp into hist without losing the data?

I probably could set up FillHist to return a TH1F instead, but for my use case I’d like to pass and fill/combine 3 different histograms which is trickier to return

_ROOT Version:6.20.04
_Platform:CentOS
_Compiler:gcc-9.3.0

void FillHist(TH1F* &hist)

Thanks that works, Do you mind giving me a quick explanation as too why it works? The part I don’t understand is how this relates to the Clone(). For example if I don’t clone and just fill the histogram:

void FillHist(TH1F* hist)
{
    hist->Fill(0.5);
    cout<<hist->GetEntries()<<endl;
}
void MWE()
{
    TH1F* hist = new TH1F("h","h",10,0,1);
    FillHist(hist);
    cout<<hist->GetEntries()<<endl;
}

I get an output of 1 and 1. So why is the & not needed here while it is for the Clone version?

Uncle Google → C++ reference to pointer

So why does the second example work then? The google result suggests it should only work with the &. To quote the first google result: “But the problem comes when you modify the pointer inside the function. Instead of modifying the variable, you are only modifying a copy of the pointer and the original pointer remains unmodified.”

Isn’t that what I’m doing in the second example? Yet it still successfully modifies the original pointer

In your “second example”, you directly modify the original histogram.

I think I sort of see the difference. From what I understand it seems to not require the & if I don’t overwrite the histogram with a new object.
So switching the Clone to Add also solves my original question.

hist->Add(temp,1);

instead of

hist = (TH1F*)temp->Clone();

I think my remaining uncertainties on the difference between requiring the & or not is a c++ issue and not a root problem though, so I’ll study it elsewhere.

Thanks for your help!