2010-05-22 105 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