使用 reinterpreter_cast 读写二进制文件
Read and write binary file with reinterpreter_cast
例如,如果我有一个名为 Obj
的 class 和一个名为 obj1
的 Obj
。当我想用 reinterpret_cast
写入二进制文件时,我以二进制模式打开该文件,然后
outstream.write( reinterpret_cast<const char *>(&obj1), sizeof(obj1) )
其中 outstream 是一个 ifstream。
当我想从那个文件中读取时,
instream.read( reinterpret_cast<char *>(&obj1), sizeof(obj1) )
发生了什么。它以二进制读取 obj1
的表示形式并转换为 obj1
或它是如何工作的。当我写的时候我明白它解释 obj1
一个字节但是当我读的时候我不明白会发生什么。
当您将指向对象的指针重新解释为指向 char
的指针时,您将写入对象本身的内存表示。这包括
- 对象内部的所有指针。对于具有虚拟成员的类,这可能包括指向 vtable 的指针,具体取决于实现
- 成员之间的所有填充,
- 所有数据成员,以您的硬件字节序排列。
此写入不包括指针指向的对象的任何部分。
而且,当你将一个带有指针的对象读回内存时,这些指针中的值将是垃圾。如果取消引用其中任何一个,就会出现未定义的行为。
这使得该技术仅适用于普通旧数据 (POD) 对象,即基元和 structs/classes 由基元和其他 POD 对象组成。此外,当您需要跨硬件兼容性时,该技术不适用。
比如说,class Obj
的一个对象在内存中占用了 4 个字节。
[OBJ] = [0][1][2][3]
= FF FF FF FF //(for example, all bytes contain 0xFF)
A char
,正常情况下,占用1个字节。因此,当您执行 reinterpret_cast
时,您的对象将被 处理 作为 4 个单独的字节(可以说是一个字符数组)。
当您以这种方式序列化您的对象时,您将存储 0
到 3
的原始字节,并且您的文件将包含 4
个字节 0xFF 0xFF 0xFF 0xFF
。底线是将原始字节复制到文件中。
反序列化就这么简单,你有一个占位符Obj要读入,然后文件中的相同字节将覆盖对象。
有一个警告。这种序列化仅适用于具有简单数据成员的 POD 类型或结构。像这样,
struct Foo {
int bar1;
float bar2;
};
它不适用于 std::vector
或 std::list
等。
一般来说它不会对指针起作用,因为如果你存储原始值(地址),指针包含它在下次你 运行 你的程序并读取这个地址时将毫无意义。反序列化后,您的对象将包含无效指针。
例如,如果我有一个名为 Obj
的 class 和一个名为 obj1
的 Obj
。当我想用 reinterpret_cast
写入二进制文件时,我以二进制模式打开该文件,然后
outstream.write( reinterpret_cast<const char *>(&obj1), sizeof(obj1) )
其中 outstream 是一个 ifstream。
当我想从那个文件中读取时,
instream.read( reinterpret_cast<char *>(&obj1), sizeof(obj1) )
发生了什么。它以二进制读取 obj1
的表示形式并转换为 obj1
或它是如何工作的。当我写的时候我明白它解释 obj1
一个字节但是当我读的时候我不明白会发生什么。
当您将指向对象的指针重新解释为指向 char
的指针时,您将写入对象本身的内存表示。这包括
- 对象内部的所有指针。对于具有虚拟成员的类,这可能包括指向 vtable 的指针,具体取决于实现
- 成员之间的所有填充,
- 所有数据成员,以您的硬件字节序排列。
此写入不包括指针指向的对象的任何部分。
而且,当你将一个带有指针的对象读回内存时,这些指针中的值将是垃圾。如果取消引用其中任何一个,就会出现未定义的行为。
这使得该技术仅适用于普通旧数据 (POD) 对象,即基元和 structs/classes 由基元和其他 POD 对象组成。此外,当您需要跨硬件兼容性时,该技术不适用。
比如说,class Obj
的一个对象在内存中占用了 4 个字节。
[OBJ] = [0][1][2][3]
= FF FF FF FF //(for example, all bytes contain 0xFF)
A char
,正常情况下,占用1个字节。因此,当您执行 reinterpret_cast
时,您的对象将被 处理 作为 4 个单独的字节(可以说是一个字符数组)。
当您以这种方式序列化您的对象时,您将存储 0
到 3
的原始字节,并且您的文件将包含 4
个字节 0xFF 0xFF 0xFF 0xFF
。底线是将原始字节复制到文件中。
反序列化就这么简单,你有一个占位符Obj要读入,然后文件中的相同字节将覆盖对象。
有一个警告。这种序列化仅适用于具有简单数据成员的 POD 类型或结构。像这样,
struct Foo {
int bar1;
float bar2;
};
它不适用于 std::vector
或 std::list
等。
一般来说它不会对指针起作用,因为如果你存储原始值(地址),指针包含它在下次你 运行 你的程序并读取这个地址时将毫无意义。反序列化后,您的对象将包含无效指针。