将fwrite()与类一起使用会发生什么?

时间:2010-12-29 00:04:42

标签: c++ class

假设我有以下内容:

class dataClass {
public:
    int someData;
    float moreData;
    void setData();
};
dataClass data;
如果我拨打fwrite(&data, sizeof(data), 1, outputFilePointer);会怎么样?代码是否就像dataClass没有任何功能一样,或者我是否必须与每个成员联系fwrite()

5 个答案:

答案 0 :(得分:4)

只要您的班级是POD类型,它就可以正常工作,您的班级就是。

答案 1 :(得分:3)

在这种情况下,你的类是POD,所以它就像它是一个普通的旧C结构一样工作,即它会将data的内存表示转储到磁盘上(包括填充字节)编译器可以插入)。

然而,如果virtual方法,virtual继承和其他C ++的东西开始,你可能会开始看到奇怪的东西(你不仅会看到你的普通数据字段,还会看到指向它的指针vtable,也许是编译器自动输入的其他东西);我认为多重继承可能会增加混乱。

请注意,在某个对象上调用fwrite在每种情况下都应该是无害的(虽然它可能是未指定的行为,但我没有检查);如果您尝试仅使用fread从文件反序列化非POD对象,则可能会出现问题(例如,正确的vtable指针可能被存储在文件中的指针覆盖,可能不再有效,这将使下一次虚拟通话中的一切都爆炸。)

答案 2 :(得分:1)

在C ++中,每个对象都由一个字节序列表示,任何类型的对象都可以重新解释为一个字节数组。这正是当你调用fwrite时会发生的事情:你给它一个指向你对象的指针,并告诉它你的对象有多大(以字节为单位),它将对象重新解释为一个包含那么多字节的数组。

类型是否为POD并不重要;非POD类型的对象也可以重新解释为字节数组。关于将非POD类型对象重新解释为字节数组没有任何未定义。 (结果主要是针对非POD类型的实现定义,但这完全是另一个问题。)

非POD类型的对象的问题是,一旦你制作了它的底层存储的副本(例如使用fwrite或者在内存中的某个其他位置),就不会有很多你可以用副本做。您不能将fread副本重新存回内存并期望将其用作原始对象,并且您无法重新解释字节副本,就好像它们是原始对象类型的对象一样。 / p>

类似的问题存在于具有指针类型的数据成员的类中,即使这些类是POD类:因为您只复制了指针的值而不是指针引用的对象,所以你没有实际上复制了你需要的所有数据。你无法从文件中有意义地读取复制的数据,因为你最终会得到一些不涉及实际对象的指针,这当然不是你的意图。

正如其他人所说,即使你有一个自包含的POD类型的对象,你也无法将结构写入这样的文件,并期望它们在其他平台上正确读回在funamental类型的大小和表示,以及其他实现定义的事情,如数据结构填充和对齐。

答案 3 :(得分:0)

除非你有动态分配的成员,否则结构的简单memcpy(实际上就是这个)将正常工作(警告:仅在同一平台上,即endian和32/64)

答案 4 :(得分:0)

由于这是一个POD类,因此可以将其视为一个字节桶。