Variable size array workaround

Dear experts,

I want to fill a ttree with event and track related objects. So for each event-related observable I have a number of tracks that is the size of the array of the track-related observable.

the way I initialised them is as follows:
Double_t fEventObs(0.);
Int_t nTracks = fTracks->GetEntriesFast();
Double_t fTrackObs[nTracks]{}; - and this var array is filled in a loop after tracks.

I don’t know if this way of initialisation is wrong or not, but I had no problem compiling and executing my task. however on other compilers, this does not work due to the variable size initialisation of the array.

Is there a workaround for initialising these arrays, but keeping the same output?

Many thanks and cheers!

It looks like this problem is not related to ROOT but rather to C arrays - “Variable-sized object may not be initialized”: “The problem in your code is that at the time when the compilers sees your variable declaration it cannot know how many elements there are in the array.”

As a solution, I would suggest you to avoid C arrays and rather use ROOT::RVecD fTrackObs(nTracks) or std::vector<Double_t> fTrackObs(nTracks) to initaialize a vector with nTracks number of zeros.

thank you for your reply!
The problem is that I fill the array as follows:
for(int i=0; i<nTracks; i++)
{
TObjArray *t = (TObjArray *)(*fTracks)[i];
fTrackObs[i] = t->Obs();
}
This can be done with a vector in a similar manner?

If you change the initialization to either RVec or std::vector this part should remain unaffected.

The actual difference between C arrays and these vectors is in which segment of memory the vector/array is created. Since the size is not known at compile time, you will be allocating memory on the heap, and if you really want to stick to C arrays you should consider using dynamic arrays. You can of course write your own dynamic arrays with C and some malloc function, but then 1. you are responsible to deallocate its buffer and 2. check explicitly if you have enough memory on the heap when reallocating.
Hence, a viable solution for your use case seems very likely to be the usage RVec or std::vector.

Is there any problem with doing fTrackObs[i] = t->Obs(); when using ROOT::RVecD fTrackObs(nTracks) (and everything else is unchanged)?