Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Split a vector into 2 subranges without reallocating memory

Tags:

c++

stl

Let's say I have a container (vector) cont and an iterator split pointing somewhere in the container.

I want to obtain two subranges [cont.begin(), split) and [split, cont.end()) using the memory of the initial container - or maybe the initial container will shrink to the first subrange and the remaining memory will be stolen by the second.

If I was working with manually allocated arrays, I'd have someting like :

double *cont; // the 'container' - memory was allocated for this
int sz;       // the size of the container
int cap;      // the capacity of the container

Then (since I'm manually doing the bookeeping) I could introduce a new 'container'

double *slice = cont + split; // in this context split is an index and not an iterator
int slice_sz  = sz - split;
int slice_cap = capacity - split;

So then the 'container' would be updated as

sz -= split;
cap = split;

Is this doable with STL ? Can I use the existing chunk of memory and have two containers with updated members (size, capacity etc ... I suppose the hack of passing .data has no meaning)

PS

I'm aware the standard solution would be to work with iterator ranges, but I have a context where I need to work with complete containers, so [begin, split) and [split, end) is not any good.

like image 471
Nikos Athanasiou Avatar asked Feb 13 '23 00:02

Nikos Athanasiou


2 Answers

You can't have two "containers", but you can have two iterator ranges.

vector<double> v;
vector<double>::iterator split = v.begin() + offset;

do_something(v.begin(), split);
do_something(split, v.end());

So the question becomes, what sort of operations do you want to perform on your two ranges?

like image 167
Useless Avatar answered Mar 03 '23 10:03

Useless


As you already mention slices, you could have a look at std::valarray and see if that fits your requirements better.

std::valarray v(n);
auto first = v.slice(0, split, 1);
auto second = v.slice(split, v.size() - split, 1);

This gives you two slices referencing the original valarray.

like image 27
Jens Avatar answered Mar 03 '23 09:03

Jens