Correct way to set the size of a std::vector
Solution 1
You're doing things in the wrong order.
resize
to the max size you want your buffer to accept.- Store the data (which must be smaller than the vector size).
resize
to the real data size.
Your problem of "disappearing data" is because when you copy the data the first time, your vector has no size only capacity (ie. pre-reserved memory without actually using it to hold data). When you reserve
again, the size is still 0 so the vector is free to optimize out the data copy since it knows it must only keep the first size()
elements (ie. 0).
In other words:
capacity()
= how much data you could put in the vector without triggering reallocation.size()
= how much data you're really using (and the vector will keep only that data across reallocations)
What's more, accessing the vector elements past its current size()
is Undefined Behaviour (it may appear to work with integral types but think about what would happen with uninitialized objects...). Don't do that.
Solution 2
recv
straight into the buffer, something along the lines of:
std::vector< unsigned char > buffer( 1024 );
buffer.resize( recv( &buffer[0], buffer.size() ) );
Depending on if recv can return error codes you might have to check before resizing.
Devolus
Assembly, C/C++, SQL and Java developer. Been working in the industry for over 20 years now, and still love programming for a hobby.
Updated on June 14, 2022Comments
-
Devolus over 1 year
From what I read,
std::vector
is the appropriate structure to use when interfacing with c function requiring a contiguous memory byte array. However I was wondering how I can determine the size of the array in some casesI have written a small sample program to illustrate what I mean.
int main(int argc, char *argv[]) { std::vector<unsigned char>v; unsigned char p[1024]; sprintf((char*)&p[0], "%10d", 10); cout << "Size: " << v.size() << " Length: " << v.capacity() << endl; v.reserve(30); cout << "Size: " << v.size() << " Length: " << v.capacity() << endl; memcpy(&v[0], &p[0], 20); cout << "Size: " << v.size() << " Length: " << v.capacity() << endl; v.reserve(50); cout << "Size: " << v.size() << " Length: " << v.capacity() << endl; v.reserve(0); cout << "Size: " << v.size() << " Length: " << v.capacity() << endl; v.resize(20); cout << "Size: " << v.size() << " Length: " << v.capacity() << endl; v.resize(0); cout << "Size: " << v.size() << " Length: " << v.capacity() << endl; return 0; }
The output is (not much surprising):
Size: 0 Length: 0 Size: 0 Length: 30 Size: 0 Length: 30 Size: 0 Length: 50 Size: 0 Length: 50 Size: 20 Length: 50 Size: 0 Length: 50
The reason why I did this is, because I reserve a buffer of a certain size and then pass this memory to a socket via
recv()
. Since I have to pass the memory as a pointer, there is no way that the vector size gets adjusted according to whatrecv
returns. Now when the received number of bytes is smaller then the buffer, I would have thought that I can somehow adjust the size of the vector, so when I pass it back, the caller can dov.size()
and the the number of elements aka returned by receive.When I looked at the data from the above example, when using
resize()
the size of the buffer is adjusted correctly, but the data is gone. So do I really have to copy the memory individually into a new vector just to get the correct size? This sounds like a really unnecessary overhead to me. Or is there some way to tell the vector how many elements it currently is supposed to hold? -
James Kanze over 10 yearsIf you don't set the size before, you'll never see what
recv
got. (Also, of course, you have undefined behavior.) -
Devolus over 10 yearsAnd this will guaruantee that the data is not lost during the resize? Because this is what I simulated with the memcpy in the short sample. When I call receive, the OS will place the data from the socket into the buffer and I'm aware that the vector can not how much this is. That's why I need to adjust size() afterwards, so the vector knows how much elements it holds, but it obviously shouldn't loose the data in the process, which apparently it does, because the vector implementation only cares about the known elements.
-
Matteo Italia over 10 years@Devolus: the vector is initialized to hold 1024 elements, so it already knows that there are 1024 valid elements (on which
recv
writes);resize
will just correct the element count to the actually used elements and (perhaps) trim the memory used. -
Devolus over 10 yearsThanks, that was indeed the correct answer and I verified it with my testprogram in the debugger. Now I also understand why. :) This also fits my implementation model, as I don't use the constructor in the beginning but want to set the size manually.
-
James Kanze over 10 years@MatteoItalia
resize
cannot reallocate unless it needs to, so it cannot make the buffer smaller. In C++11, there is a functionstd::vector<>::shrink_to_fit
which can be used to reduce the memory used, or you can do something likestd::vector< unsigned char >( v.begin(), v.end() ).swap( v );
.