In C we use char*
to point to a block of memory allocated with malloc
and keep track of the size in a separate size/length variable.
What is the C++ equivalent? From what I've seen so far most people use std::vector
. Typically .resize()
is called to allocate the required memory and then data can be memcpy
ed into .data()
.
Personally I think std::vector
shouldn't be used as a fixed size byte buffer.
Imagine we have a library which returns a std::vector<byte>
representing a fixed size byte buffer. We may encounter these problems:
- Needlessly dynamic: When we pass our fixed size byte buffer around to various functions they're free to
push_back
orinsert
new data to the buffer. The intention is a fixed size buffer. The ability to dynamically size it is unnecessary, unwanted and confusing. - Unwieldy: If we want to avoid copying the buffer all the time we have to use combinations of
std::move
, passing by reference and passing.data()
and.size()
. And if you forget astd::move
somewhere the whole thing will be accidentally copied. This is needlessly over-complicated and just annoying in my opinion. In many cases I think a raw array allocated with (malloc
/free
ornew[]
/delete[]
and wrapped in astd::span
?) would be easier to manage and less confusing, although surely there's a better C++ solution? - Default initialization: People are using
std::vector
to store raw buffers when it default initializes all elements!? - Incompatible with C libraries: There's no way to release the underlying buffer from the grasps of the vectors destructor. So if you pass
.data()
into, for example, azip_add_file(char* name, char* buffer, size_t len)
function, the vector must remain alive untilzip_write_files()
is called which frees all the given buffers. Even if it does, when it does die it will try to free the already freed memory. And there's no way to specify allocators or deallocators so the zip library will cause undefined behavior when it frees the buffer anyway.
So is there a better way?