2010-05-22 107 views
0

以下函数将结构写入文件。将结构和类写入磁盘

#define PAGESIZE sizeof(BTPAGE) 
#define HEADERSIZE 2L 

    int btwrite(short rrn, BTPAGE *page_ptr) 
    { 
     long addr; 
     addr = (long) rrn * (long) PAGESIZE + HEADERSIZE; 
     lseek(btfd, addr, 0); 
     return (write(btfd, page_ptr, PAGESIZE)); 
    } 

以下是结构。

typedef struct { 
    short keycount;    /* number of keys in page */ 
    int key[MAXKEYS];    /* the actual keys  */ 
    int value[MAXKEYS];   /* the actual values  */ 
    short child[MAXKEYS+1];  /* ptrs to rrns of descendants */ 
} BTPAGE; 

如果我将结构更改为类,会发生什么情况会发生什么?

如果我添加了类函数,它在磁盘上占用的大小会增加吗?

回答

4

东西有你需要在这里学到了很多考虑。

  • 首先,您将结构视为一个字节数组。由于strict aliasing rule,这是严格未定义的行为。任何事情都可能发生。所以不要这样做。改用正确的序列号(例如通过boost)。是的,这很乏味。是的,这是必要的。
  • 即使您忽略未定义,并选择依赖于某个特定的编译器实现(即使在下一个编译器版本中该实现可能会发生更改),仍然有理由不这样做。
    • 如果您节省一台机器上的一个文件,然后加载它另一个,你可能会得到垃圾,因为第二该机采用了不同的浮点表示,或不同endianness,或有不同的alignment rules
    • 如果你的结构体包含任何指针,那么很可能逐字保存并加载它们将导致地址不会指向任何有意义的地方。
  • 通常当你添加一个成员函数,出现这种情况:
    • 功能的机器代码存储在由所有的类实例共享的地方(这是没有意义的重复它,因为它是在逻辑上不可变)
    • 隐藏的“this”指针在被调用时传递给函数,因此它知道它被调用的是哪个对象。
    • 这些都不需要实例中的任何存储空间。
  • 但是,当您添加至少一个虚拟函数,编译器通常需要同时添加一个名为vtable一个数据块(读了它)。这使得可以根据对象的当前运行时类型(又称多态)调用不同的代码。所以你添加到类中的第一个虚拟函数可能是确实增加了对象大小
+3

关于严格别名,允许将任何POD类型的对象视为字节数组。任何类型的对象都可以通过char *来访问,并且将组成POD类型对象的字节复制到一个char数组中,然后将这些字节复制回相同POD类型的对象中。 (当然,关于不可移植性的观点仍然有效)。 – 2010-05-22 20:12:59

1

如果这个类有任何虚函数,那么你有麻烦;如果没有虚函数,你应该仍然可以(当然,这同样适用于struct,因为它也可以具有虚函数:struct和class之间的区别就在于,struct中的默认可见性是公共的,在类中它是私人的)。

3

在C++中,structclass之间的区别在于,结构的成员和基类是默认情况下公开的,而对于类,默认情况下它们是私有的。

简单地将结构字节写入文件然后再次读回文件的技术只有在结构为plain old data, or POD, type时才起作用。如果你修改你的结构体,使其不再是POD,这种技术不能保证能够工作(规则描述了什么使得POD结构体被列在链接问题的答案中)。

0

如果你正在做的类的更多系列化使用谷歌协议缓冲区,或类似see this question