Re: bug in TH operator=

From: George Heintzelman (gah@bnl.gov)
Date: Thu Sep 02 1999 - 17:08:45 MEST


Rene writes:

> Replace your doit() function by the following:
> void doit()
> {
>   TH1F a("aap","aap",4,0,4);
>   TH1F b("noot","noot",4,0,4);
>   TH1F c = a+b;
>   c.SetName("mies"); c.SetTitle("mies");
>   printf("--nr: %d------\n",gDirectory->GetList()->GetSize());
>   gDirectory->GetList()->Print();
> }

The reason this solution 'works' is that TH1F::operator= is never 
called.  The line:

TH1F c = a+b;

is executed by the compiler in exactly the same way as:

TH1F c(a+b); 

i.e. it calls the copy constructor TH1F(TH1F &) on the temporary object 
returned by operator+.

If you are providing an assignment operator for the class, you ought to 
make sure that the assignment operator works correctly.  If you want to 
disallow the assignment operator (which is what your solution amounts 
to), you should declare operator= private, and never define it.

George Heintzelman
gah@bnl.gov

Eddy Offermann wrote:
> > To illustrate this run the following macro:
> > 
> > void doit()
> > {
> >   TH1F c("mies","mies",4,0,4);
> >   TH1F a("aap","aap",4,0,4);
> >   TH1F b("noot","noot",4,0,4);
> >   c = a+b;
> >   printf("--nr: %d------\n",gDirectory->GetList()->GetSize());
> >   gDirectory->GetList()->Print();
> > }
> > 
> > Int_t test()
> > {
> >   TH1F d("schip","schip",4,0,4);
> >   printf("--nr: %d------\n",gDirectory->GetList()->GetSize());
> >   gDirectory->GetList()->Print();
> > 
> >   doit();
> > 
> >   printf("--nr: %d------\n",gDirectory->GetList()->GetSize());
> >   gDirectory->GetList()->Print();
> > }
> > 
> > The result is
> > 
> > cub:/work/eddy/ROOT/src> root -l
> >   *******************************************
> >   *                                         *
> >   *        W E L C O M E  to  R O O T       *
> >   *                                         *
> >   *   Version   2.22/09      13 July 1999   *
> >   *                                         *
> >   *  You are welcome to visit our Web site  *
> >   *          http://root.cern.ch            *
> >   *                                         *
> >   *******************************************
> > 
> > CINT/ROOT C/C++ Interpreter version 5.14.8, Jul 4 1999
> > Type ? for help. Commands must be C++ statements.
> > Enclose multiple statements between { }.
> > root [0] .L effe.C
> > root [1] test()
> > --nr: 1------
> > TH1.Print Name= schip, Total sum= 0
> > --nr: 5------
> > TH1.Print Name= schip, Total sum= 0
> > TH1.Print Name= aap, Total sum= 0
> > TH1.Print Name= aap, Total sum= 0
> > TH1.Print Name= noot, Total sum= 0
> > TH1.Print Name= aap, Total sum= 0
> > --nr: 2------
> > TH1.Print Name= schip, Total sum= 0
> > 
> >  *** Break *** segmentation violation
> > Root >
> > 
> > The operator definition should have been
> > 
> > //______________________________________________________________________________
> > TH1F& TH1F::operator=(const TH1F &h1)
> > {
> >    if (this != &h1)
> >    {
> >      fDirectory->GetList()->Remove(this); // this line has been added
> >      ((TH1F&)h1).Copy(*this);
> >    }
> >    return *this;
> > }
> > 
> > and the result is
> > 
> > --nr: 1------
> > TH1.Print Name= schip, Total sum= 0
> > --nr: 4------
> > TH1.Print Name= schip, Total sum= 0
> > TH1.Print Name= aap, Total sum= 0
> > TH1.Print Name= noot, Total sum= 0
> > TH1.Print Name= aap, Total sum= 0
> > --nr: 1------
> > TH1.Print Name= schip, Total sum= 0
> > 
> > Eddy



This archive was generated by hypermail 2b29 : Tue Jan 04 2000 - 00:43:39 MET