With vectors, one can assume that elements are stored contiguously in memory, allowing the range [&vec[0], &vec[vec.capacity()) to be used as a normal array. E.g.,
vector<char> buf; buf.reserve(N); int M = read(fd, &buf[0], N);
But now the vector doesn't know that it contains M bytes of data, added externally by read(). I know that vector::resize() sets the size, but it also clears the data, so it can't be used to update the size after the read() call.
Is there a trivial way to read data directly into vectors and update the size after? Yes, I know of the obvious workarounds like using a small array as a temporary read buffer, and using vector::insert() to append that to the end of the vector:
char tmp[N]; int M = read(fd, tmp, N); buf.insert(buf.end(), tmp, tmp + M)
This works (and it's what I'm doing today), but it just bothers me that there is an extra copy operation there that would not be required if I could put the data directly into the vector.
So, is there a simple way to modify the vector size when data has been added externally?
C++ Vector Library - resize() Function The C++ function std::vector::resize() changes the size of vector. If n is smaller than current size then extra elements are destroyed. If n is greater than current container size then new elements are inserted at the end of vector.
Resizing a vector doesn't destroy the values stored in the vector (except for those beyond the new size when shrinking, of course), however growing a vector beyond its capacity will copy (or, in C++11, move) them to a new place, thus invalidating and iterators, pointers or references to those elements.
The idea is to insert all vector elements in a set and copy the set's contents back again into the vector. This works as inserting elements into the set removes all duplicates as all set elements must be distinct. Please note that this might change the original ordering of elements in the vector.
Begin Declare v of vector type. Call push_back() function to insert values into vector v. Print “Vector elements:”. for (int a : v) print all the elements of variable a.
vector<char> buf; buf.reserve(N); int M = read(fd, &buf[0], N);
This code fragment invokes undefined behavior. You can't write beyond than size()
elements, even if you have reserved the space.
The correct code is like:
vector<char> buf; buf.resize(N); int M = read(fd, &buf[0], N); buf.resize(M);
[&vec[0], &vec[vec.capacity())
to be used as a normal array" isn't true. The allowable range is [&vec[0], &vec[vec.size())
.
It looks like you can do what you want in C++11 (though I haven't tried this myself). You'll have to define a custom allocator for the vector, then use emplace_back()
.
First, define
struct do_not_initialize_tag {};
Then define your allocator with this member function:
class my_allocator { void construct(char* c, do_not_initialize_tag) const { // do nothing } // details omitted // ... }
Now you can add elements to your array without initializing them:
std::vector<char, my_allocator> buf; buf.reserve(N); for (int i = 0; i != N; ++i) buf.emplace_back(do_not_initialize_tag()); int M = read(fd, buf.data(), N); buf.resize(M);
The efficiency of this depends on the compiler's optimizer. For instance, the loop may increment the size member variable N times.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With