Does there exist a type similar to std::string (i.e., holding blobs of data of arbitrary length) that does not use the null terminator?

Viewed 109

I use std::string to hold arbitrary blobs of binary data. It works this way, but is slightly inefficient as it needs to add the null terminator to the end of the blob. (C++11 spec is that c_str() and data() are the same, and return a pointer to a blob with a null terminator at the end.) Is there a better type to use, that still supports common operations (copy constructor, assignment operator, etc)?

2 Answers

Use the right tool for the job. A std::string is designed to store and manipulate sequences of char-like objects. This incorporates a mechanism (std::char_traits) to define text processing, which can be used to introduce more overhead than the terminating null character. As one example, the character traits could be used to sort strings case-insensitively. Blobs of binary data are not "text", so a string is not a great semantic fit for the job at hand.

The best fit for binary data is std::byte, but that was not introduced until C++17, and this question is tagged C++11. The pre-17 options are char and unsigned char (and std::uint8_t, if that type is provided and if you don't need to do type aliasing); I would recommend the latter since signed types add semantics not applicable to raw binary data.

Once you've picked the basic unit for your data, you need to collect several of these units into a container. When in doubt - when you have no particular reason to choose one container over another - use a std::vector, as that tends to perform well in many circumstances. (Not to mention that the functionality of a std::string is that of a std::vector<char> plus additional string functionality. You want to eliminate the overhead of the additional string functionality, right?)

std::vector<std::byte>      // C++17
std::vector<unsigned char>  // Earlier standards
Related