使用std::string存储二进制数据
std::string这个标准容器,不仅可以用来存储字符串。还可以用于存储二进制数据。从本质上讲它算不上字符串,它就是个char容器。
在c++11之后,为了充分地性能优化,手动为一个数据类去写move构造等函数用于支持移动语意是必要的,尤其对于用于存储二进制数据的类型。
举个栗子,我们希望使用Msg存储二进制消息,写一个支持移动语意的类(不用仔细看):
#include <cstddef>
#include <cstring>
#include <string>
typedef unsigned char byte;
struct Msg {
size_t len = 0;
byte* data = nullptr;
inline void initMsg(const byte* data = nullptr, size_t len = 0) {
if (data == nullptr || len == 0) {
this->len = 0;
this->data = nullptr;
return;
}
this->len = len;
this->data = new byte[len];
memcpy(this->data, data, len);
}
inline void moveMsg(Msg& msg) {
this->len = msg.len;
this->data = msg.data;
msg.data = nullptr;
}
explicit Msg(const byte* data = nullptr, size_t len = 0) {
initMsg(data, len);
}
Msg(const Msg& msg) {
initMsg(msg.data, msg.len);
}
Msg(Msg&& msg) noexcept {
moveMsg(msg);
}
Msg& operator=(const Msg& msg) {
if (&msg == this)
return *this;
delete[] this->data;
initMsg(msg.data, msg.len);
return *this;
}
Msg& operator=(Msg&& msg) noexcept {
if (&msg == this)
return *this;
delete[] this->data;
moveMsg(msg);
return *this;
}
std::string toString() {
return std::string((char*)data, 0, len);
}
~Msg() {
delete[] data;
}
};
怎么样?是不是很麻烦。。。
确实大多数时候并不需要特别定制数据类型,我们可以使用标准容器如std::vector<uint8_t>或者std::string。其中,std::string使用比较方便,很多开源项目也使用了这个数据容器传递消息/payload。
注意在使用之前最好先进行类型准换:
auto data = reinterpret_cast<const uint8_t*>(mystring.data());