假设我有以下内容:
class dataClass {
public:
int someData;
float moreData;
void setData();
};
dataClass data;
如果我拨打fwrite(&data, sizeof(data), 1, outputFilePointer);
会怎么样?代码是否就像dataClass
没有任何功能一样,或者我是否必须与每个成员联系fwrite()
?
答案 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类,因此可以将其视为一个字节桶。