Is it possible to extract data from std::vector without copying it? (and make the vector forget it)

Viewed 366

I have a std::vector<byte> object and I want to extract data from it without copying. It may contain megabytes of data. So, if I copy data I would lose performance. Is it possible to extract the data from the vector and make it forget about data, that is, that it doesn't free memory for the data after destruction? Hope for your help! Thanks in advance!

P.S: extract in this case means just get a raw pointer to the data and make vector forget about it (i.e don't free the memory after destruction)

3 Answers

No, It is not possible to extract part of data from vector as far as I know.

It is not compatible with structure of vector that provides its data in a continuous part of memory. std::vector memory is continues, so if it was possible to move part of its memory to another place, you need to shift reminder of memory to keep it continuous. It will be a huge burden itself.

I personally suggest to pass main vector by pointer/reference and use required parts directly as needed.

If you need to move whole data of std::vector to another place, you can just use std::move() to do so. You can even use std::swap() to swap contents of 2 vector together.

I have a std::vector object and I want to extract data from it without copying

You can move the entire contents of a vector ... into a different vector. Or you can swap (the contents of) two vectors.

std::vector<byte> v = get_a_big_vector();
std::vector<byte> w = std::move(v); // now w owns the large allocation
std::vector<byte> x;
std::swap(x,y); // now x owns the large allocation, and w is empty

That's it. You can't ask a vector to release its storage, and you can't somehow "take" just a portion of a contiguous allocation without affecting the rest.

You can move-assign some sub-range of elements, but that's only different to copying if the elements are some kind of object with state stored outside the instance (eg, a long std::string).

If you really need to take just a sub-range and let the rest be deallocated, then a vector isn't really the right data type. Something like a rope is designed for this, or you can just split your single contiguous vector into a vector of 1Mb (or whatever) chunk indirections. This is actually something like a deque (although you can't steal chunks from std::deque either).

I think the best way is to use an object orineted approach. You can abstract byte data inside a class with other information like a flag to make them to be skipped or forget:

class Data
{
public:
   Data(byte d)
   {
       data = d;
       forget = false;
   }
   byte data;
   bool forget;
}

Then just add to the vector pointers to data like

vector<Data*> data;
data.push_back(new Data(1));    
data.push_back(new Data(2));
// and so on

You can extract data without copying just getting the pointers to specific element of the array:

Data *d = data[index];
d->forget = true;

You can use the forget flag to make it forgettable. Of course you have to manage the forget flag yourself when searching the vector. You can use the std::find_if with a lamba expression for this porpouse.

Keep in mind you have to free memory when data is not used any more.

Related