Devolus
Devolus

Reputation: 22074

Correct way to set the size of a std::vector

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

Answers (4)

syam
syam

Reputation: 15069

You're doing things in the wrong order.

  1. resize to the max size you want your buffer to accept.
  2. Store the data (which must be smaller than the vector size).
  3. 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

Oleg
Oleg

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

softwarebear
softwarebear

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

Ylisar
Ylisar

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

Related Questions