使用 reinterpreter_cast 读写二进制文件

Read and write binary file with reinterpreter_cast

例如,如果我有一个名为 Obj 的 class 和一个名为 obj1Obj。当我想用 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 个单独的字节(可以说是一个字符数组)。

当您以这种方式序列化您的对象时,您将存储 03 的原始字节,并且您的文件将包含 4 个字节 0xFF 0xFF 0xFF 0xFF。底线是将原始字节复制到文件中。

反序列化就这么简单,你有一个占位符Obj要读入,然后文件中的相同字节将覆盖对象。


有一个警告。这种序列化仅适用于具有简单数据成员的 POD 类型或结构。像这样,

struct Foo {
    int bar1;
    float bar2;
};

它不适用于 std::vectorstd::list 等。 一般来说它不会对指针起作用,因为如果你存储原始值(地址),指针包含它在下次你 运行 你的程序并读取这个地址时将毫无意义。反序列化后,您的对象将包含无效指针。