Logo ROOT  
Reference Guide
TClonesArray.cxx
Go to the documentation of this file.
1 // @(#)root/cont:$Id$
2 // Author: Rene Brun 11/02/96
3 
4 /*************************************************************************
5  * Copyright (C) 1995-2000, Rene Brun and Fons Rademakers. *
6  * All rights reserved. *
7  * *
8  * For the licensing terms see $ROOTSYS/LICENSE. *
9  * For the list of contributors see $ROOTSYS/README/CREDITS. *
10  *************************************************************************/
11 
12 /** \class TClonesArray
13 \ingroup Containers
14 An array of clone (identical) objects. Memory for the objects
15 stored in the array is allocated only once in the lifetime of the
16 clones array. All objects must be of the same class. For the rest
17 this class has the same properties as TObjArray.
18 
19 To reduce the very large number of new and delete calls in large
20 loops like this (O(100000) x O(10000) times new/delete):
21 ~~~ {.cpp}
22  TObjArray a(10000);
23  while (TEvent *ev = (TEvent *)next()) { // O(100000) events
24  for (int i = 0; i < ev->Ntracks; i++) { // O(10000) tracks
25  a[i] = new TTrack(x,y,z,...);
26  ...
27  ...
28  }
29  ...
30  a.Delete();
31  }
32 ~~~
33 One better uses a TClonesArray which reduces the number of
34 new/delete calls to only O(10000):
35 ~~~ {.cpp}
36  TClonesArray a("TTrack", 10000);
37  while (TEvent *ev = (TEvent *)next()) { // O(100000) events
38  for (int i = 0; i < ev->Ntracks; i++) { // O(10000) tracks
39  new(a[i]) TTrack(x,y,z,...);
40  ...
41  ...
42  }
43  ...
44  a.Delete(); // or a.Clear() or a.Clear("C")
45  }
46 ~~~
47 To reduce the number of call to the constructor (especially useful
48 if the user class requires memory allocation), the object can be
49 added (and constructed when needed) using ConstructedAt which only
50 calls the constructor once per slot.
51 ~~~ {.cpp}
52  TClonesArray a("TTrack", 10000);
53  while (TEvent *ev = (TEvent *)next()) { // O(100000) events
54  for (int i = 0; i < ev->Ntracks; i++) { // O(10000) tracks
55  TTrack *track = (TTrack*)a.ConstructedAt(i);
56  track->Set(x,y,z,....);
57  ...
58  ...
59  }
60  ...
61  a.Clear(); // or a.Clear("C");
62  }
63 ~~~
64 Note: the only supported way to add objects to a TClonesArray is
65 via the new with placement method or the ConstructedAt method.
66 The other Add() methods ofTObjArray and its base classes are not
67 allowed.
68 
69 Considering that a new/delete costs about 70 mus on a 300 MHz HP,
70 O(10^9) new/deletes will save about 19 hours.
71 
72 ### NOTE 1
73 
74 C/C++ offers the possibility of allocating and deleting memory.
75 Forgetting to delete allocated memory is a programming error called a
76 "memory leak", i.e. the memory of your process grows and eventually
77 your program crashes. Even if you *always* delete the allocated
78 memory, the recovered space may not be efficiently reused. The
79 process knows that there are portions of free memory, but when you
80 allocate it again, a fresh piece of memory is grabbed. Your program
81 is free from semantic errors, but the total memory of your process
82 still grows, because your program's memory is full of "holes" which
83 reduce the efficiency of memory access; this is called "memory
84 fragmentation". Moreover new / delete are expensive operations in
85 terms of CPU time.
86 
87 Without entering into technical details, TClonesArray allows you to
88 "reuse" the same portion of memory for new/delete avoiding memory
89 fragmentation and memory growth and improving the performance by
90 orders of magnitude. Every time the memory of the TClonesArray has
91 to be reused, the Clear() method is used. To provide its benefits,
92 each TClonesArray must be allocated *once* per process and disposed
93 of (deleted) *only when not needed any more*.
94 
95 So a job should see *only one* deletion for each TClonesArray,
96 which should be Clear()ed during the job several times. Deleting a
97 TClonesArray is a double waste. Not only you do not avoid memory
98 fragmentation, but you worsen it because the TClonesArray itself
99 is a rather heavy structure, and there is quite some code in the
100 destructor, so you have more memory fragmentation and slower code.
101 
102 ### NOTE 2
103 
104 When investigating misuse of TClonesArray, please make sure of the following:
105 
106  - Use Clear() or Clear("C") instead of Delete(). This will improve
107  program execution time.
108  - TClonesArray object classes containing pointers allocate memory.
109  To avoid causing memory leaks, special Clear("C") must be used
110  for clearing TClonesArray. When option "C" is specified, ROOT
111  automatically executes the Clear() method (by default it is
112  empty contained in TObject). This method must be overridden in
113  the relevant TClonesArray object class, implementing the reset
114  procedure for pointer objects.
115  - If the objects are added using the placement new then the Clear must
116  deallocate the memory.
117  - If the objects are added using TClonesArray::ConstructedAt then the
118  heap-based memory can stay allocated and reused as the constructor is
119  not called for already constructed/added object.
120  - To reduce memory fragmentation, please make sure that the
121  TClonesArrays are not destroyed and created on every event. They
122  must only be constructed/destructed at the beginning/end of the
123  run.
124 */
125 
126 #include "TClonesArray.h"
127 
128 #include "TError.h"
129 #include "TROOT.h"
130 #include "TBuffer.h"
131 #include "TClass.h"
132 #include "TObject.h"
133 #include "TObjectTable.h"
134 #include "snprintf.h"
135 
136 #include <cstdlib>
137 
139 
140 // To allow backward compatibility of TClonesArray of v5 TF1 objects
141 // that were stored member-wise.
142 using Updater_t = void (*)(Int_t nobjects, TObject **from, TObject **to);
145 
147  gClonesArrayTF1Updater = func;
148  return true;
149 }
150 
153  return true;
154 }
155 
156 /// Internal Utility routine to correctly release the memory for an object
157 static inline void R__ReleaseMemory(TClass *cl, TObject *obj)
158 {
159  if (obj && obj->TestBit(TObject::kNotDeleted)) {
160  // -- The TObject destructor has not been called.
161  cl->Destructor(obj);
162  } else {
163  // -- The TObject destructor was called, just free memory.
164  //
165  // remove any possible entries from the ObjectTable
168  }
169  ::operator delete(obj);
170  }
171 }
172 
173 
174 ////////////////////////////////////////////////////////////////////////////////
175 /// Default Constructor.
176 
178 {
179  fClass = 0;
180  fKeep = 0;
181 }
182 
183 ////////////////////////////////////////////////////////////////////////////////
184 /// Create an array of clone objects of classname. The class must inherit from
185 /// TObject.
186 /// The second argument s indicates an approximate number of objects
187 /// that will be entered in the array. If more than s objects are entered,
188 /// the array will be automatically expanded.
189 ///
190 /// The third argument is not used anymore and only there for backward
191 /// compatibility reasons.
192 
193 TClonesArray::TClonesArray(const char *classname, Int_t s, Bool_t) : TObjArray(s)
194 {
195  fKeep = 0;
196  SetClass(classname,s);
197 }
198 
199 ////////////////////////////////////////////////////////////////////////////////
200 /// Create an array of clone objects of class cl. The class must inherit from
201 /// TObject.
202 /// The second argument, s, indicates an approximate number of objects
203 /// that will be entered in the array. If more than s objects are entered,
204 /// the array will be automatically expanded.
205 ///
206 /// The third argument is not used anymore and only there for backward
207 /// compatibility reasons.
208 
210 {
211  fKeep = 0;
212  SetClass(cl,s);
213 }
214 
215 ////////////////////////////////////////////////////////////////////////////////
216 /// Copy ctor.
217 
219 {
220  fKeep = new TObjArray(tc.fSize);
221  fClass = tc.fClass;
222 
224 
225  for (Int_t i = 0; i < fSize; i++) {
226  if (tc.fCont[i]) fCont[i] = tc.fCont[i]->Clone();
227  fKeep->fCont[i] = fCont[i];
228  }
229 }
230 
231 ////////////////////////////////////////////////////////////////////////////////
232 /// Assignment operator.
233 
235 {
236  if (this == &tc) return *this;
237 
238  if (fClass != tc.fClass) {
239  Error("operator=", "cannot copy TClonesArray's when classes are different");
240  return *this;
241  }
242 
243  if (tc.fSize > fSize)
245 
246  Int_t i;
247 
248  for (i = 0; i < fSize; i++)
249  if (fKeep->fCont[i]) {
251  fKeep->fCont[i] = nullptr;
252  fCont[i] = nullptr;
253  }
254 
256 
257  for (i = 0; i < tc.fSize; i++) {
258  if (tc.fCont[i]) fKeep->fCont[i] = tc.fCont[i]->Clone();
259  fCont[i] = fKeep->fCont[i];
260  }
261 
262  fLast = tc.fLast;
263  Changed();
264  return *this;
265 }
266 
267 ////////////////////////////////////////////////////////////////////////////////
268 /// Delete a clones array.
269 
271 {
272  if (fKeep) {
273  for (Int_t i = 0; i < fKeep->fSize; i++) {
275  fKeep->fCont[i] = nullptr;
276  }
277  }
278  SafeDelete(fKeep);
279 
280  // Protect against erroneously setting of owner bit
281  SetOwner(kFALSE);
282 }
283 
284 ////////////////////////////////////////////////////////////////////////////////
285 /// When the kBypassStreamer bit is set, the automatically
286 /// generated Streamer can call directly TClass::WriteBuffer.
287 /// Bypassing the Streamer improves the performance when writing/reading
288 /// the objects in the TClonesArray. However there is a drawback:
289 /// When a TClonesArray is written with split=0 bypassing the Streamer,
290 /// the StreamerInfo of the class in the array being optimized,
291 /// one cannot use later the TClonesArray with split>0. For example,
292 /// there is a problem with the following scenario:
293 /// 1. A class Foo has a TClonesArray of Bar objects
294 /// 2. The Foo object is written with split=0 to Tree T1.
295 /// In this case the StreamerInfo for the class Bar is created
296 /// in optimized mode in such a way that data members of the same type
297 /// are written as an array improving the I/O performance.
298 /// 3. In a new program, T1 is read and a new Tree T2 is created
299 /// with the object Foo in split>1
300 /// 4. When the T2 branch is created, the StreamerInfo for the class Bar
301 /// is created with no optimization (mandatory for the split mode).
302 /// The optimized Bar StreamerInfo is going to be used to read
303 /// the TClonesArray in T1. The result will be Bar objects with
304 /// data member values not in the right sequence.
305 /// The solution to this problem is to call BypassStreamer(kFALSE)
306 /// for the TClonesArray. In this case, the normal Bar::Streamer function
307 /// will be called. The Bar::Streamer function works OK independently
308 /// if the Bar StreamerInfo had been generated in optimized mode or not.
309 
311 {
312  if (bypass)
314  else
316 }
317 
318 ////////////////////////////////////////////////////////////////////////////////
319 /// Remove empty slots from array.
320 
322 {
323  Int_t j = 0, je = 0;
324 
325  TObject **tmp = new TObject* [fSize];
326 
327  for (Int_t i = 0; i < fSize; i++) {
328  if (fCont[i]) {
329  fCont[j] = fCont[i];
330  fKeep->fCont[j] = fKeep->fCont[i];
331  j++;
332  } else {
333  tmp[je] = fKeep->fCont[i];
334  je++;
335  }
336  }
337 
338  fLast = j - 1;
339 
340  Int_t jf = 0;
341  for ( ; j < fSize; j++) {
342  fCont[j] = 0;
343  fKeep->fCont[j] = tmp[jf];
344  jf++;
345  }
346 
347  delete [] tmp;
348 
349  R__ASSERT(je == jf);
350 }
351 
352 ////////////////////////////////////////////////////////////////////////////////
353 /// Get an object at index 'idx' that is guaranteed to have been constructed.
354 /// It might be either a freshly allocated object or one that had already been
355 /// allocated (and assumingly used). In the later case, it is the callers
356 /// responsibility to insure that the object is returned to a known state,
357 /// usually by calling the Clear method on the TClonesArray.
358 ///
359 /// Tests to see if the destructor has been called on the object.
360 /// If so, or if the object has never been constructed the class constructor is called using
361 /// New(). If not, return a pointer to the correct memory location.
362 /// This explicitly to deal with TObject classes that allocate memory
363 /// which will be reset (but not deallocated) in their Clear()
364 /// functions.
365 
367 {
368  TObject *obj = (*this)[idx];
369  if ( obj && obj->TestBit(TObject::kNotDeleted) ) {
370  return obj;
371  }
372  return (fClass) ? static_cast<TObject*>(fClass->New(obj)) : 0;
373 }
374 
375 ////////////////////////////////////////////////////////////////////////////////
376 /// Get an object at index 'idx' that is guaranteed to have been constructed.
377 /// It might be either a freshly allocated object or one that had already been
378 /// allocated (and assumingly used). In the later case, the function Clear
379 /// will be called and passed the value of 'clear_options'
380 ///
381 /// Tests to see if the destructor has been called on the object.
382 /// If so, or if the object has never been constructed the class constructor is called using
383 /// New(). If not, return a pointer to the correct memory location.
384 /// This explicitly to deal with TObject classes that allocate memory
385 /// which will be reset (but not deallocated) in their Clear()
386 /// functions.
387 
389 {
390  TObject *obj = (*this)[idx];
391  if ( obj && obj->TestBit(TObject::kNotDeleted) ) {
392  obj->Clear(clear_options);
393  return obj;
394  }
395  return (fClass) ? static_cast<TObject*>(fClass->New(obj)) : 0;
396 }
397 
398 ////////////////////////////////////////////////////////////////////////////////
399 /// Clear the clones array. Only use this routine when your objects don't
400 /// allocate memory since it will not call the object dtors.
401 /// However, if the class in the TClonesArray implements the function
402 /// Clear(Option_t *option) and if option = "C" the function Clear()
403 /// is called for all objects in the array. In the function Clear(), one
404 /// can delete objects or dynamic arrays allocated in the class.
405 /// This procedure is much faster than calling TClonesArray::Delete().
406 /// When the option starts with "C+", eg "C+xyz" the objects in the array
407 /// are in turn cleared with the option "xyz"
408 
410 {
411  if (option && option[0] == 'C') {
412  const char *cplus = strstr(option,"+");
413  if (cplus) {
414  cplus = cplus + 1;
415  } else {
416  cplus = "";
417  }
418  Int_t n = GetEntriesFast();
419  for (Int_t i = 0; i < n; i++) {
420  TObject *obj = UncheckedAt(i);
421  if (obj) {
422  obj->Clear(cplus);
423  obj->ResetBit( kHasUUID );
424  obj->ResetBit( kIsReferenced );
425  obj->SetUniqueID( 0 );
426  }
427  }
428  }
429 
430  // Protect against erroneously setting of owner bit
431  SetOwner(kFALSE);
432 
434 }
435 
436 ////////////////////////////////////////////////////////////////////////////////
437 /// Clear the clones array. Use this routine when your objects allocate
438 /// memory (e.g. objects inheriting from TNamed or containing TStrings
439 /// allocate memory). If not you better use Clear() since if is faster.
440 
442 {
444  // In case of emulated class, we can not use the delete operator
445  // directly, it would use the wrong destructor.
446  for (Int_t i = 0; i < fSize; i++) {
447  if (fCont[i] && fCont[i]->TestBit(kNotDeleted)) {
449  }
450  }
451  } else {
452  for (Int_t i = 0; i < fSize; i++) {
453  if (fCont[i] && fCont[i]->TestBit(kNotDeleted)) {
454  fCont[i]->~TObject();
455  }
456  }
457  }
458 
459  // Protect against erroneously setting of owner bit.
460  SetOwner(kFALSE);
461 
463 }
464 
465 ////////////////////////////////////////////////////////////////////////////////
466 /// Expand or shrink the array to newSize elements.
467 
469 {
470  if (newSize < 0) {
471  Error ("Expand", "newSize must be positive (%d)", newSize);
472  return;
473  }
474  if (!fKeep) {
475  Error("ExpandCreate", "Not initialized properly, fKeep is still a nullptr");
476  return;
477  }
478  if (newSize == fSize)
479  return;
480  if (newSize < fSize) {
481  // release allocated space in fKeep and set to 0 so
482  // Expand() will shrink correctly
483  for (int i = newSize; i < fSize; i++)
484  if (fKeep->fCont[i]) {
486  fKeep->fCont[i] = nullptr;
487  }
488  }
489 
490  TObjArray::Expand(newSize);
491  fKeep->Expand(newSize);
492 }
493 
494 ////////////////////////////////////////////////////////////////////////////////
495 /// Expand or shrink the array to n elements and create the clone
496 /// objects by calling their default ctor. If n is less than the current size
497 /// the array is shrunk and the allocated space is freed.
498 /// This routine is typically used to create a clonesarray into which
499 /// one can directly copy object data without going via the
500 /// "new (arr[i]) MyObj()" (i.e. the vtbl is already set correctly).
501 
503 {
504  if (n < 0) {
505  Error("ExpandCreate", "n must be positive (%d)", n);
506  return;
507  }
508  if (!fKeep) {
509  Error("ExpandCreate", "Not initialized properly, fKeep is still a nullptr");
510  return;
511  }
512  if (n > fSize)
514 
515  Int_t i;
516  for (i = 0; i < n; i++) {
517  if (!fKeep->fCont[i]) {
518  fKeep->fCont[i] = (TObject*)fClass->New();
519  } else if (!fKeep->fCont[i]->TestBit(kNotDeleted)) {
520  // The object has been deleted (or never initialized)
521  fClass->New(fKeep->fCont[i]);
522  }
523  fCont[i] = fKeep->fCont[i];
524  }
525 
526  for (i = n; i < fSize; i++)
527  if (fKeep->fCont[i]) {
529  fKeep->fCont[i] = nullptr;
530  fCont[i] = nullptr;
531  }
532 
533  fLast = n - 1;
534  Changed();
535 }
536 
537 ////////////////////////////////////////////////////////////////////////////////
538 /// Expand or shrink the array to n elements and create the clone
539 /// objects by calling their default ctor. If n is less than the current size
540 /// the array is shrunk but the allocated space is _not_ freed.
541 /// This routine is typically used to create a clonesarray into which
542 /// one can directly copy object data without going via the
543 /// "new (arr[i]) MyObj()" (i.e. the vtbl is already set correctly).
544 /// This is a simplified version of ExpandCreate used in the TTree mechanism.
545 
547 {
548  Int_t oldSize = fKeep->GetSize();
549  if (n > fSize)
551 
552  Int_t i;
553  for (i = 0; i < n; i++) {
554  if (i >= oldSize || !fKeep->fCont[i]) {
555  fKeep->fCont[i] = (TObject*)fClass->New();
556  } else if (!fKeep->fCont[i]->TestBit(kNotDeleted)) {
557  // The object has been deleted (or never initialized)
558  fClass->New(fKeep->fCont[i]);
559  }
560  fCont[i] = fKeep->fCont[i];
561  }
562  if (fLast >= n) {
563  memset(fCont + n, 0, (fLast - n + 1) * sizeof(TObject*));
564  }
565  fLast = n - 1;
566  Changed();
567 }
568 
569 ////////////////////////////////////////////////////////////////////////////////
570 /// Remove object at index idx.
571 
573 {
574  if (!BoundsOk("RemoveAt", idx)) return 0;
575 
576  int i = idx-fLowerBound;
577 
578  if (fCont[i] && fCont[i]->TestBit(kNotDeleted)) {
579  fCont[i]->~TObject();
580  }
581 
582  if (fCont[i]) {
583  fCont[i] = 0;
584  // recalculate array size
585  if (i == fLast)
586  do { fLast--; } while (fLast >= 0 && fCont[fLast] == 0);
587  Changed();
588  }
589 
590  return 0;
591 }
592 
593 ////////////////////////////////////////////////////////////////////////////////
594 /// Remove object from array.
595 
597 {
598  if (!obj) return 0;
599 
600  Int_t i = IndexOf(obj) - fLowerBound;
601 
602  if (i == -1) return 0;
603 
604  if (fCont[i] && fCont[i]->TestBit(kNotDeleted)) {
605  fCont[i]->~TObject();
606  }
607 
608  fCont[i] = 0;
609  // recalculate array size
610  if (i == fLast)
611  do { fLast--; } while (fLast >= 0 && fCont[fLast] == 0);
612  Changed();
613  return obj;
614 }
615 
616 ////////////////////////////////////////////////////////////////////////////////
617 /// Remove objects from index idx1 to idx2 included.
618 
620 {
621  if (!BoundsOk("RemoveRange", idx1)) return;
622  if (!BoundsOk("RemoveRange", idx2)) return;
623 
624  idx1 -= fLowerBound;
625  idx2 -= fLowerBound;
626 
627  Bool_t change = kFALSE;
628  for (TObject **obj=fCont+idx1; obj<=fCont+idx2; obj++) {
629  if (!*obj) continue;
630  if ((*obj)->TestBit(kNotDeleted)) {
631  (*obj)->~TObject();
632  }
633  *obj = 0;
634  change = kTRUE;
635  }
636 
637  // recalculate array size
638  if (change) Changed();
639  if (idx1 < fLast || fLast > idx2) return;
640  do { fLast--; } while (fLast >= 0 && fCont[fLast] == 0);
641 }
642 
643 ////////////////////////////////////////////////////////////////////////////////
644 /// Create an array of clone objects of class cl. The class must inherit from
645 /// TObject.
646 /// The second argument s indicates an approximate number of objects
647 /// that will be entered in the array. If more than s objects are entered,
648 /// the array will be automatically expanded.
649 ///
650 /// NB: This function should not be called in the TClonesArray is already
651 /// initialized with a class.
652 
654 {
655  if (fKeep) {
656  Error("SetClass", "TClonesArray already initialized with another class");
657  return;
658  }
659  fClass = (TClass*)cl;
660  if (!fClass) {
661  MakeZombie();
662  Error("SetClass", "called with a null pointer");
663  return;
664  }
665  const char *classname = fClass->GetName();
666  if (!fClass->IsTObject()) {
667  MakeZombie();
668  Error("SetClass", "%s does not inherit from TObject", classname);
669  return;
670  }
672  MakeZombie();
673  Error("SetClass", "%s must inherit from TObject as the left most base class.", classname);
674  return;
675  }
676  Int_t nch = strlen(classname)+2;
677  char *name = new char[nch];
678  snprintf(name,nch, "%ss", classname);
679  SetName(name);
680  delete [] name;
681 
682  fKeep = new TObjArray(s);
683 
685 }
686 
687 ////////////////////////////////////////////////////////////////////////////////
688 ///see TClonesArray::SetClass(const TClass*)
689 
690 void TClonesArray::SetClass(const char *classname, Int_t s)
691 {
692  SetClass(TClass::GetClass(classname),s);
693 }
694 
695 
696 ////////////////////////////////////////////////////////////////////////////////
697 /// A TClonesArray is always the owner of the object it contains.
698 /// However the collection its inherits from (TObjArray) does not.
699 /// Hence this member function needs to be a nop for TClonesArray.
700 
701 void TClonesArray::SetOwner(Bool_t /* enable */)
702 {
703  // Nothing to be done.
704 }
705 
706 ////////////////////////////////////////////////////////////////////////////////
707 /// If objects in array are sortable (i.e. IsSortable() returns true
708 /// for all objects) then sort array.
709 
711 {
712  Int_t nentries = GetAbsLast()+1;
713  if (nentries <= 0 || fSorted) return;
714  for (Int_t i = 0; i < fSize; i++)
715  if (fCont[i]) {
716  if (!fCont[i]->IsSortable()) {
717  Error("Sort", "objects in array are not sortable");
718  return;
719  }
720  }
721 
723 
724  fLast = -2;
725  fSorted = kTRUE;
726 }
727 
728 ////////////////////////////////////////////////////////////////////////////////
729 /// Write all objects in array to the I/O buffer. ATTENTION: empty slots
730 /// are also stored (using one byte per slot). If you don't want this
731 /// use a TOrdCollection or TList.
732 
733 void TClonesArray::Streamer(TBuffer &b)
734 {
735  // Important Note: if you modify this function, remember to also modify
736  // TConvertClonesArrayToProxy accordingly
737 
738  Int_t nobjects;
739  char nch;
740  TString s, classv;
741  UInt_t R__s, R__c;
742 
743  if (b.IsReading()) {
744  Version_t v = b.ReadVersion(&R__s, &R__c);
745  if (v == 3) {
746  const Int_t kOldBypassStreamer = BIT(14);
747  if (TestBit(kOldBypassStreamer)) BypassStreamer();
748  }
749  if (v > 2)
750  TObject::Streamer(b);
751  if (v > 1)
752  fName.Streamer(b);
753  s.Streamer(b);
754  classv = s;
755  Int_t clv = 0;
756  Ssiz_t pos = s.Index(";");
757  if (pos != kNPOS) {
758  classv = s(0, pos);
759  s = s(pos+1, s.Length()-pos-1);
760  clv = s.Atoi();
761  }
762  TClass *cl = TClass::GetClass(classv);
763  if (!cl) {
764  Error("Streamer", "expecting class %s but it was not found by TClass::GetClass\n",
765  classv.Data());
766  b.CheckByteCount(R__s, R__c,TClonesArray::IsA());
767  return;
768  }
769 
770  b >> nobjects;
771  if (nobjects < 0)
772  nobjects = -nobjects; // still there for backward compatibility
773  b >> fLowerBound;
774  if (fClass == 0) {
775  fClass = cl;
776  if (fKeep == 0) {
777  fKeep = new TObjArray(fSize);
778  Expand(nobjects);
779  }
780  } else if (cl != fClass && classv == fClass->GetName()) {
781  // If fClass' name is different from classv, the user has intentionally changed
782  // the target class, so we must not override it.
783  fClass = cl;
784  //this case may happen when switching from an emulated class to the real class
785  //may not be an error. fClass may point to a deleted object
786  //Error("Streamer", "expecting objects of type %s, finding objects"
787  // " of type %s", fClass->GetName(), cl->GetName());
788  //return;
789  }
790 
791  // make sure there are enough slots in the fKeep array
792  if (fKeep->GetSize() < nobjects)
793  Expand(nobjects);
794 
795  //reset fLast. nobjects may be 0
796  Int_t oldLast = fLast;
797  fLast = nobjects-1;
798 
799  //TStreamerInfo *sinfo = fClass->GetStreamerInfo(clv);
801  for (Int_t i = 0; i < nobjects; i++) {
802  if (!fKeep->fCont[i]) {
803  fKeep->fCont[i] = (TObject*)fClass->New();
804  } else if (!fKeep->fCont[i]->TestBit(kNotDeleted)) {
805  // The object has been deleted (or never initialized)
806  fClass->New(fKeep->fCont[i]);
807  }
808 
809  fCont[i] = fKeep->fCont[i];
810  }
811  if (clv < 8 && classv == "TF1") {
812  // To allow backward compatibility of TClonesArray of v5 TF1 objects
813  // that were stored member-wise.
814  TClonesArray temp("ROOT::v5::TF1Data");
815  temp.ExpandCreate(nobjects);
816  b.ReadClones(&temp, nobjects, clv);
817  // And now covert the v5 into the current
819  gClonesArrayTF1Updater(nobjects, temp.GetObjectRef(nullptr), this->GetObjectRef(nullptr));
820  } else if (clv <= 8 && clv > 3 && clv != 6 && classv == "TFormula") {
821  // To allow backwar compatibility of TClonesArray of v5 TF1 objects
822  // that were stored member-wise.
823  TClonesArray temp("ROOT::v5::TFormula");
824  temp.ExpandCreate(nobjects);
825  b.ReadClones(&temp, nobjects, clv);
826  // And now covert the v5 into the current
828  gClonesArrayTFormulaUpdater(nobjects, temp.GetObjectRef(nullptr), this->GetObjectRef(nullptr));
829  } else {
830  // sinfo->ReadBufferClones(b,this,nobjects,-1,0);
831  b.ReadClones(this, nobjects, clv);
832  }
833  } else {
834  for (Int_t i = 0; i < nobjects; i++) {
835  b >> nch;
836  if (nch) {
837  if (!fKeep->fCont[i])
838  fKeep->fCont[i] = (TObject*)fClass->New();
839  else if (!fKeep->fCont[i]->TestBit(kNotDeleted)) {
840  // The object has been deleted (or never initialized)
841  fClass->New(fKeep->fCont[i]);
842  }
843 
844  fCont[i] = fKeep->fCont[i];
845  b.StreamObject(fKeep->fCont[i]);
846  }
847  }
848  }
849  for (Int_t i = TMath::Max(nobjects,0); i < oldLast+1; ++i) fCont[i] = 0;
850  Changed();
851  b.CheckByteCount(R__s, R__c,TClonesArray::IsA());
852  } else {
853  //Make sure TStreamerInfo is not optimized, otherwise it will not be
854  //possible to support schema evolution in read mode.
855  //In case the StreamerInfo has already been computed and optimized,
856  //one must disable the option BypassStreamer
857  b.ForceWriteInfoClones(this);
858 
859  // make sure the status of bypass streamer is part of the buffer
860  // (bits in TObject), so that when reading the object the right
861  // mode is used, independent of the method (e.g. written via
862  // TMessage, received and stored to a file and then later read via
863  // TBufferFile)
864  Bool_t bypass = kFALSE;
866  bypass = CanBypassStreamer();
868  }
869 
870  R__c = b.WriteVersion(TClonesArray::IsA(), kTRUE);
871  TObject::Streamer(b);
872  fName.Streamer(b);
873  s.Form("%s;%d", fClass->GetName(), fClass->GetClassVersion());
874  s.Streamer(b);
875  nobjects = GetEntriesFast();
876  b << nobjects;
877  b << fLowerBound;
878  if (CanBypassStreamer()) {
879  b.WriteClones(this,nobjects);
880  } else {
881  for (Int_t i = 0; i < nobjects; i++) {
882  if (!fCont[i]) {
883  nch = 0;
884  b << nch;
885  } else {
886  nch = 1;
887  b << nch;
888  b.StreamObject(fCont[i]);
889  }
890  }
891  }
892  b.SetByteCount(R__c, kTRUE);
893 
894  if (bypass)
895  BypassStreamer();
896  }
897 }
898 
899 ////////////////////////////////////////////////////////////////////////////////
900 /// Return pointer to reserved area in which a new object of clones
901 /// class can be constructed. This operator should not be used for
902 /// lefthand side assignments, like a[2] = xxx. Only like,
903 /// new (a[2]) myClass, or xxx = a[2]. Of course right hand side usage
904 /// is only legal after the object has been constructed via the
905 /// new operator or via the New() method. To remove elements from
906 /// the clones array use Remove() or RemoveAt().
907 
909 {
910  if (idx < 0) {
911  Error("operator[]", "out of bounds at %d in %lx", idx, (Long_t)this);
912  return fCont[0];
913  }
914  if (!fClass) {
915  Error("operator[]", "invalid class specified in TClonesArray ctor");
916  return fCont[0];
917  }
918  if (idx >= fSize)
919  Expand(TMath::Max(idx+1, GrowBy(fSize)));
920 
921  if (!fKeep->fCont[idx]) {
923  // Reset the bit so that:
924  // obj = myClonesArray[i];
925  // obj->TestBit(TObject::kNotDeleted)
926  // will behave correctly.
927  // TObject::kNotDeleted is one of the higher bit that is not settable via the public
928  // interface. But luckily we are its friend.
929  fKeep->fCont[idx]->fBits &= ~kNotDeleted;
930  }
931  fCont[idx] = fKeep->fCont[idx];
932 
933  fLast = TMath::Max(idx, GetAbsLast());
934  Changed();
935 
936  return fCont[idx];
937 }
938 
939 ////////////////////////////////////////////////////////////////////////////////
940 /// Return the object at position idx. Returns 0 if idx is out of bounds.
941 
943 {
944  if (idx < 0 || idx >= fSize) {
945  Error("operator[]", "out of bounds at %d in %lx", idx, (Long_t)this);
946  return 0;
947  }
948 
949  return fCont[idx];
950 }
951 
952 ////////////////////////////////////////////////////////////////////////////////
953 /// Create an object of type fClass with the default ctor at the specified
954 /// index. Returns 0 in case of error.
955 
957 {
958  if (idx < 0) {
959  Error("New", "out of bounds at %d in %lx", idx, (Long_t)this);
960  return 0;
961  }
962  if (!fClass) {
963  Error("New", "invalid class specified in TClonesArray ctor");
964  return 0;
965  }
966 
967  return (TObject *)fClass->New(operator[](idx));
968 }
969 
970 //______________________________________________________________________________
971 //
972 // The following functions are utilities implemented by Jason Detwiler
973 // (jadetwiler@lbl.gov)
974 //
975 ////////////////////////////////////////////////////////////////////////////////
976 /// Directly move the object pointers from tc without cloning (copying).
977 /// This TClonesArray takes over ownership of all of tc's object
978 /// pointers. The tc array is left empty upon return.
979 
981 {
982  // tests
983  if (tc == 0 || tc == this || tc->GetEntriesFast() == 0) return;
984  AbsorbObjects(tc, 0, tc->GetEntriesFast() - 1);
985 }
986 
987 ////////////////////////////////////////////////////////////////////////////////
988 /// Directly move the range of object pointers from tc without cloning
989 /// (copying).
990 /// This TClonesArray takes over ownership of all of tc's object pointers
991 /// from idx1 to idx2. The tc array is re-arranged by return.
992 
994 {
995  // tests
996  if (tc == 0 || tc == this || tc->GetEntriesFast() == 0) return;
997  if (fClass != tc->fClass) {
998  Error("AbsorbObjects", "cannot absorb objects when classes are different");
999  return;
1000  }
1001 
1002  if (idx1 > idx2) {
1003  Error("AbsorbObjects", "range is not valid: idx1>idx2");
1004  return;
1005  }
1006  if (idx2 >= tc->GetEntriesFast()) {
1007  Error("AbsorbObjects", "range is not valid: idx2 out of bounds");
1008  return;
1009  }
1010 
1011  // cache the sorted status
1012  Bool_t wasSorted = IsSorted() && tc->IsSorted() &&
1013  (Last() == 0 || Last()->Compare(tc->First()) == -1);
1014 
1015  // expand this
1016  Int_t oldSize = GetEntriesFast();
1017  Int_t newSize = oldSize + (idx2-idx1+1);
1018  if(newSize > fSize)
1019  Expand(newSize);
1020 
1021  // move
1022  for (Int_t i = idx1; i <= idx2; i++) {
1023  Int_t newindex = oldSize+i -idx1;
1024  fCont[newindex] = tc->fCont[i];
1025  R__ReleaseMemory(fClass,fKeep->fCont[newindex]);
1026  (*fKeep)[newindex] = (*(tc->fKeep))[i];
1027  tc->fCont[i] = 0;
1028  (*(tc->fKeep))[i] = 0;
1029  }
1030 
1031  // cleanup
1032  for (Int_t i = idx2+1; i < tc->GetEntriesFast(); i++) {
1033  tc->fCont[i-(idx2-idx1+1)] = tc->fCont[i];
1034  (*(tc->fKeep))[i-(idx2-idx1+1)] = (*(tc->fKeep))[i];
1035  tc->fCont[i] = 0;
1036  (*(tc->fKeep))[i] = 0;
1037  }
1038  tc->fLast = tc->GetEntriesFast() - 2 - (idx2 - idx1);
1039  fLast = newSize-1;
1040  if (!wasSorted)
1041  Changed();
1042 }
1043 
1044 ////////////////////////////////////////////////////////////////////////////////
1045 /// Sort multiple TClonesArrays simultaneously with this array.
1046 /// If objects in array are sortable (i.e. IsSortable() returns true
1047 /// for all objects) then sort array.
1048 
1050 {
1051  Int_t nentries = GetAbsLast()+1;
1052  if (nentries <= 1 || fSorted) return;
1053  Bool_t sortedCheck = kTRUE;
1054  for (Int_t i = 0; i < fSize; i++) {
1055  if (fCont[i]) {
1056  if (!fCont[i]->IsSortable()) {
1057  Error("MultiSort", "objects in array are not sortable");
1058  return;
1059  }
1060  }
1061  if (sortedCheck && i > 1) {
1062  if (ObjCompare(fCont[i], fCont[i-1]) < 0) sortedCheck = kFALSE;
1063  }
1064  }
1065  if (sortedCheck) {
1066  fSorted = kTRUE;
1067  return;
1068  }
1069 
1070  for (int i = 0; i < nTCs; i++) {
1071  if (tcs[i] == this) {
1072  Error("MultiSort", "tcs[%d] = \"this\"", i);
1073  return;
1074  }
1075  if (tcs[i]->GetEntriesFast() != GetEntriesFast()) {
1076  Error("MultiSort", "tcs[%d] has length %d != length of this (%d)",
1077  i, tcs[i]->GetEntriesFast(), this->GetEntriesFast());
1078  return;
1079  }
1080  }
1081 
1082  int nBs = nTCs*2+1;
1083  TObject*** b = new TObject**[nBs];
1084  for (int i = 0; i < nTCs; i++) {
1085  b[2*i] = tcs[i]->fCont;
1086  b[2*i+1] = tcs[i]->fKeep->fCont;
1087  }
1088  b[nBs-1] = fKeep->fCont;
1089  QSort(fCont, nBs, b, 0, TMath::Min(nentries, upto-fLowerBound));
1090  delete [] b;
1091 
1092  fLast = -2;
1093  fSorted = kTRUE;
1094 }
n
const Int_t n
Definition: legend1.C:16
TClonesArray::CanBypassStreamer
Bool_t CanBypassStreamer() const
Definition: TClonesArray.h:64
TClonesArray::fClass
TClass * fClass
Definition: TClonesArray.h:32
TClass::kIsEmulation
@ kIsEmulation
Definition: TClass.h:100
kTRUE
const Bool_t kTRUE
Definition: RtypesCore.h:91
TObject::TestBit
R__ALWAYS_INLINE Bool_t TestBit(UInt_t f) const
Definition: TObject.h:172
TCollection::IsSortable
Bool_t IsSortable() const
Definition: TCollection.h:189
Version_t
short Version_t
Definition: RtypesCore.h:65
snprintf
#define snprintf
Definition: civetweb.c:1540
TObjArray
An array of TObjects.
Definition: TObjArray.h:37
TObjArray::BoundsOk
Bool_t BoundsOk(const char *where, Int_t at) const
Definition: TObjArray.h:159
TObjArray::GetAbsLast
Int_t GetAbsLast() const
Return absolute index to last object in array.
Definition: TObjArray.cxx:539
Option_t
const char Option_t
Definition: RtypesCore.h:66
gObjectTable
R__EXTERN TObjectTable * gObjectTable
Definition: TObjectTable.h:82
TMath::Max
Short_t Max(Short_t a, Short_t b)
Definition: TMathBase.h:212
TClonesArray::Delete
virtual void Delete(Option_t *option="")
Clear the clones array.
Definition: TClonesArray.cxx:441
kNPOS
const Ssiz_t kNPOS
Definition: RtypesCore.h:115
TClass::Size
Int_t Size() const
Return size of object of this class.
Definition: TClass.cxx:5518
TObject::Compare
virtual Int_t Compare(const TObject *obj) const
Compare abstract method.
Definition: TObject.cxx:161
TObjArray::fCont
TObject ** fCont
Definition: TObjArray.h:43
TSeqCollection::QSort
static void QSort(TObject **a, Int_t first, Int_t last)
Sort array of TObject pointers using a quicksort algorithm.
Definition: TSeqCollection.cxx:70
TClonesArray::~TClonesArray
virtual ~TClonesArray()
Delete a clones array.
Definition: TClonesArray.cxx:270
TClonesArray::New
TObject * New(Int_t idx)
Create an object of type fClass with the default ctor at the specified index.
Definition: TClonesArray.cxx:956
TString::Data
const char * Data() const
Definition: TString.h:369
ClassImp
#define ClassImp(name)
Definition: Rtypes.h:364
TObjArray::fLowerBound
Int_t fLowerBound
Array contents.
Definition: TObjArray.h:44
TObject::Error
virtual void Error(const char *method, const char *msgfmt,...) const
Issue error message.
Definition: TObject.cxx:890
gClonesArrayTF1Updater
Updater_t gClonesArrayTF1Updater
Definition: TClonesArray.cxx:143
TClonesArray::fKeep
TObjArray * fKeep
Pointer to the class of the elements.
Definition: TClonesArray.h:33
TObjArray::IndexOf
Int_t IndexOf(const TObject *obj) const
Definition: TObjArray.cxx:605
TBuffer::kCannotHandleMemberWiseStreaming
@ kCannotHandleMemberWiseStreaming
Definition: TBuffer.h:76
TGeant4Unit::s
static constexpr double s
Definition: TGeant4SystemOfUnits.h:162
Int_t
int Int_t
Definition: RtypesCore.h:45
SafeDelete
#define SafeDelete(p)
Definition: RConfig.hxx:543
TClass::GetClassVersion
Version_t GetClassVersion() const
Definition: TClass.h:377
TClass.h
nentries
int nentries
Definition: THbookFile.cxx:91
TCollection::fName
TString fName
Definition: TCollection.h:147
TBuffer
Buffer base class used for serializing objects.
Definition: TBuffer.h:43
TObjArray::UncheckedAt
TObject * UncheckedAt(Int_t i) const
Definition: TObjArray.h:90
TClonesArray::operator=
TClonesArray & operator=(const TClonesArray &tc)
Assignment operator.
Definition: TClonesArray.cxx:234
TClonesArray::Sort
virtual void Sort(Int_t upto=kMaxInt)
If objects in array are sortable (i.e.
Definition: TClonesArray.cxx:710
TString
Basic string class.
Definition: TString.h:136
R__ReleaseMemory
static void R__ReleaseMemory(TClass *cl, TObject *obj)
Internal Utility routine to correctly release the memory for an object.
Definition: TClonesArray.cxx:157
Bool_t
bool Bool_t
Definition: RtypesCore.h:63
v
@ v
Definition: rootcling_impl.cxx:3635
b
#define b(i)
Definition: RSha256.hxx:100
TClonesArray::ExpandCreate
virtual void ExpandCreate(Int_t n)
Expand or shrink the array to n elements and create the clone objects by calling their default ctor.
Definition: TClonesArray.cxx:502
bool
TObjArray::Last
TObject * Last() const
Return the object in the last filled slot. Returns 0 if no entries.
Definition: TObjArray.cxx:506
TClonesArray.h
TStorage::ObjectAlloc
static void * ObjectAlloc(size_t size)
Used to allocate a TObject on the heap (via TObject::operator new()).
Definition: TStorage.cxx:328
TROOT.h
TObject::~TObject
virtual ~TObject()
TObject destructor.
Definition: TObject.cxx:81
TSeqCollection::fSorted
Bool_t fSorted
Definition: TSeqCollection.h:31
TClonesArray::BypassStreamer
void BypassStreamer(Bool_t bypass=kTRUE)
When the kBypassStreamer bit is set, the automatically generated Streamer can call directly TClass::W...
Definition: TClonesArray.cxx:310
TClonesArray::Remove
virtual TObject * Remove(TObject *obj)
Remove object from array.
Definition: TClonesArray.cxx:596
TSeqCollection::Changed
virtual void Changed()
Definition: TSeqCollection.h:34
TClonesArray::Compress
virtual void Compress()
Remove empty slots from array.
Definition: TClonesArray.cxx:321
TBuffer.h
TObject::ResetBit
void ResetBit(UInt_t f)
Definition: TObject.h:171
TClass::New
void * New(ENewType defConstructor=kClassNew, Bool_t quiet=kFALSE) const
Return a pointer to a newly allocated object of this class.
Definition: TClass.cxx:4876
TObject::SetBit
void SetBit(UInt_t f, Bool_t set)
Set or unset the user status bits as specified in f.
Definition: TObject.cxx:696
TClonesArray::Expand
virtual void Expand(Int_t newSize)
Expand or shrink the array to newSize elements.
Definition: TClonesArray.cxx:468
TObjArray::GetEntriesFast
Int_t GetEntriesFast() const
Definition: TObjArray.h:64
kFALSE
const Bool_t kFALSE
Definition: RtypesCore.h:92
TCollection::fSize
Int_t fSize
Definition: TCollection.h:148
Long_t
long Long_t
Definition: RtypesCore.h:54
TObjArray::fLast
Int_t fLast
Definition: TObjArray.h:45
TObject::Clone
virtual TObject * Clone(const char *newname="") const
Make a clone of an object using the Streamer facility.
Definition: TObject.cxx:146
TCollection::GrowBy
virtual Int_t GrowBy(Int_t delta) const
Increase the collection's capacity by delta slots.
Definition: TCollection.cxx:360
BIT
#define BIT(n)
Definition: Rtypes.h:85
UInt_t
unsigned int UInt_t
Definition: RtypesCore.h:46
TClass::GetClass
static TClass * GetClass(const char *name, Bool_t load=kTRUE, Bool_t silent=kFALSE)
Static method returning pointer to TClass of the specified class name.
Definition: TClass.cxx:2925
TObject::MakeZombie
void MakeZombie()
Definition: TObject.h:49
TClonesArray::AbsorbObjects
void AbsorbObjects(TClonesArray *tc)
Directly move the object pointers from tc without cloning (copying).
Definition: TClonesArray.cxx:980
TObjectTable.h
TClass::IsTObject
Bool_t IsTObject() const
Return kTRUE is the class inherits from TObject.
Definition: TClass.cxx:5752
void
typedef void((*Func_t)())
TMath::Min
Short_t Min(Short_t a, Short_t b)
Definition: TMathBase.h:180
TClonesArray::operator[]
TObject *& operator[](Int_t idx)
Return pointer to reserved area in which a new object of clones class can be constructed.
Definition: TClonesArray.cxx:908
Ssiz_t
int Ssiz_t
Definition: RtypesCore.h:67
TObjArray::Clear
virtual void Clear(Option_t *option="")
Remove all objects from the array.
Definition: TObjArray.cxx:321
TObject::fBits
UInt_t fBits
bit field status word
Definition: TObject.h:41
TObject::kIsReferenced
@ kIsReferenced
if object is referenced by a TRef or TRefArray
Definition: TObject.h:61
Updater_t
void(*)(Int_t nobjects, TObject **from, TObject **to) Updater_t
Definition: TClonesArray.cxx:142
R__ASSERT
#define R__ASSERT(e)
Definition: TError.h:120
TObject::kNotDeleted
@ kNotDeleted
object has not been deleted
Definition: TObject.h:78
TObject.h
TCollection::GetSize
virtual Int_t GetSize() const
Return the capacity of the collection, i.e.
Definition: TCollection.h:182
TObject::GetObjectStat
static Bool_t GetObjectStat()
Get status of object stat flag.
Definition: TObject.cxx:964
TClonesArray::kBypassStreamer
@ kBypassStreamer
Definition: TClonesArray.h:37
TClass
TClass instances represent classes, structs and namespaces in the ROOT type system.
Definition: TClass.h:80
TSeqCollection::IsSorted
virtual Bool_t IsSorted() const
Definition: TSeqCollection.h:58
TCollection::SetName
void SetName(const char *name)
Definition: TCollection.h:204
TObjArray::Expand
virtual void Expand(Int_t newSize)
Expand or shrink the array to newSize elements.
Definition: TObjArray.cxx:387
TClass::Destructor
void Destructor(void *obj, Bool_t dtorOnly=kFALSE)
Explicitly call destructor for object.
Definition: TClass.cxx:5233
R__SetClonesArrayTF1Updater
bool R__SetClonesArrayTF1Updater(Updater_t func)
Definition: TClonesArray.cxx:146
TObject
Mother of all ROOT objects.
Definition: TObject.h:37
TClass::GetBaseClassOffset
Int_t GetBaseClassOffset(const TClass *toBase, void *address=0, bool isDerivedObject=true)
Definition: TClass.cxx:2748
name
char name[80]
Definition: TGX11.cxx:110
TClonesArray::RemoveRange
virtual void RemoveRange(Int_t idx1, Int_t idx2)
Remove objects from index idx1 to idx2 included.
Definition: TClonesArray.cxx:619
TClonesArray::SetOwner
virtual void SetOwner(Bool_t enable=kTRUE)
A TClonesArray is always the owner of the object it contains.
Definition: TClonesArray.cxx:701
TClonesArray::TClonesArray
TClonesArray()
Default Constructor.
Definition: TClonesArray.cxx:177
TClonesArray::ConstructedAt
TObject * ConstructedAt(Int_t idx)
Get an object at index 'idx' that is guaranteed to have been constructed.
Definition: TClonesArray.cxx:366
gClonesArrayTFormulaUpdater
Updater_t gClonesArrayTFormulaUpdater
Definition: TClonesArray.cxx:144
TNamed::GetName
virtual const char * GetName() const
Returns name of object.
Definition: TNamed.h:47
R__SetClonesArrayTFormulaUpdater
bool R__SetClonesArrayTFormulaUpdater(Updater_t func)
Definition: TClonesArray.cxx:151
Class
void Class()
Definition: Class.C:29
TObjectTable::RemoveQuietly
void RemoveQuietly(TObject *obj)
Remove an object from the object table.
Definition: TObjectTable.cxx:243
TObject::kHasUUID
@ kHasUUID
if object has a TUUID (its fUniqueID=UUIDNumber)
Definition: TObject.h:62
TClonesArray
An array of clone (identical) objects.
Definition: TClonesArray.h:29
TClonesArray::RemoveAt
virtual TObject * RemoveAt(Int_t idx)
Remove object at index idx.
Definition: TClonesArray.cxx:572
TClonesArray::MultiSort
void MultiSort(Int_t nTCs, TClonesArray **tcs, Int_t upto=kMaxInt)
Sort multiple TClonesArrays simultaneously with this array.
Definition: TClonesArray.cxx:1049
TObject::Clear
virtual void Clear(Option_t *="")
Definition: TObject.h:100
TClonesArray::SetClass
void SetClass(const char *classname, Int_t size=1000)
see TClonesArray::SetClass(const TClass*)
Definition: TClonesArray.cxx:690
TObjArray::First
TObject * First() const
Return the object in the first slot.
Definition: TObjArray.cxx:496
TObject::SetUniqueID
virtual void SetUniqueID(UInt_t uid)
Set the unique object id.
Definition: TObject.cxx:707
TSeqCollection::ObjCompare
static Int_t ObjCompare(TObject *a, TObject *b)
Compare to objects in the collection. Use member Compare() of object a.
Definition: TSeqCollection.cxx:56
int
TClonesArray::ExpandCreateFast
virtual void ExpandCreateFast(Int_t n)
Expand or shrink the array to n elements and create the clone objects by calling their default ctor.
Definition: TClonesArray.cxx:546
TObjArray::TObjArray
TObjArray(Int_t s=TCollection::kInitCapacity, Int_t lowerBound=0)
Create an object array.
Definition: TObjArray.cxx:64
TError.h
TClonesArray::Clear
virtual void Clear(Option_t *option="")
Clear the clones array.
Definition: TClonesArray.cxx:409