如果您不打算使用序列化库,那么我建议为每个类添加序列化支持:
struct My_Struct
{
std::string my_string;
unsigned int my_int;
void Load_From_Buffer(unsigned char const *& p_buffer)
{
my_string = std::string(p_buffer);
p_buffer += my_string.length() + 1; // +1 to account for the terminating nul character.
my_int = *((unsigned int *) p_buffer);
p_buffer += sizeof(my_int);
}
};
unsigned char * const buffer = ReadFile(filename);
unsigned char * p_buffer = buffer;
My_Struct my_variable;
my_variable.Load_From_Buffer(p_buffer);
其他一些有用的接口方法:
unsigned int Size_On_Stream(void) const; // Returns the size the object would occupy in the stream.
void Store_To_Buffer(unsigned char *& p_buffer); // Stores object to buffer, increments pointer.
使用模板,您可以扩展序列化功能:
void Load_From_Buffer(std::string& s, unsigned char *& p_buffer)
{
s = std::string((char *)p_buffer);
p_buffer += s.length() + 1;
}
void template<classtype T> Load_From_Buffer(T& object, unsigned char *& p_buffer)
{
object.Load_From_Buffer(p_buffer);
}
编辑1:不直接写结构的原因
在 C 和 C++ 中,结构的大小可能不等于其成员大小的总和。
允许编译器在成员之间插入填充或未使用的空间,以便成员在地址上对齐。
例如,32 位处理器喜欢在 4 字节边界上获取内容。在char
结构中包含一个后跟 anint
将使int
相对地址为 1,这不是 4 的倍数。编译器将填充该结构,以便int
在相对地址 4 上对齐。
结构可能包含指针或包含指针的项。
例如,std::string
类型的大小可能为 40,尽管字符串可能包含 3 个字符或 300 个字符。它有一个指向实际数据的指针。
字节序。
对于多字节整数,一些处理器如最高有效字节 (MSB),即 Big Endian,优先(人类读取数字的方式)或最低有效字节优先,即 Little Endian。小端格式比大端格式需要更少的电路来读取。
编辑 2:变体记录
在输出数组和容器之类的东西时,您必须决定是要输出完整的容器(包括未使用的插槽)还是只输出容器中的项目。仅输出容器中的项目将使用变体记录技术。
输出变体记录的两种技术:数量后跟项目或项目后跟哨兵。后者是 C 风格字符串的编写方式,哨兵是一个空字符。
另一种技术是输出项目的数量,然后是项目。所以如果我有 6 个数字,0、1、2、3、4、5,输出将是:
6 // 项目数
0
1
2
3
4
5
在上面的 Load_From_Buffer 方法中,我将创建一个临时保存数量,将其写出,然后从容器中取出每个项目。