Reputation: 22074
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 cases
I 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 what recv
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 do v.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?
Upvotes: 3
Views: 21496
Reputation: 15069
You're doing things in the wrong order.
resize
to the max size you want your buffer to accept.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.
Upvotes: 7
Reputation: 766
When you copy something to a memory location starting from vector's buffer first byte - then the vector is not aware of this and will not update its internal size counter. Use vector's assign() or insert() methods to copy the buffer to the vector.
reserve() doesn't decrease the capacity previously reserved. That is why in the last line you still see 50 nevertheless you decreased it to 20.
Upvotes: 0
Reputation: 451
v.reserve(n)
to set the capacity to n
.
m = recv(s,&v[0],n,0)
v.resize(m)
to set the vector size to what recv got.
Upvotes: 0
Reputation: 4291
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.
Upvotes: 3