2016-12-03 53 views
0

我遇到了一個課,我們使用了一個名爲「Person」的用戶定義類型,它將一個人的姓名存儲在char數組中,並將年齡作爲整數存儲起來。這節課是關於編寫和閱讀二進制文件的。主要程序是這樣的:將用戶定義的類型轉換爲char *時發生了什麼?

int main() 
{ 
Person anil("anil",24); //initialize with name and age 

fstream file("person.bin", ios::binary | ios::in | ios::out | ios::trunc); 

if (!file.is_open()) 
    cout << "Error while opening file."; 
else 
{ 
    file.write((char*)&anil, sizeof(Person)); 
    file.seekg(0); // go back to beginning 

    Person anjali; //declare new person object 

    //first argument is memory block, second argument is byte size 
    file.read((char*)&anjali, sizeof(Person)); 

    anil.whoAreYou(); //outputs the name and age 
    anjali.whoAreYou(); 
} 

return 0; 
} 

我不明白什麼是這些線路發生:

file.write((char*)&anil, sizeof(Person)); 
file.read((char*)&anjali, sizeof(Person)); 

據我所知,寫和讀的fstream的功能要求memory_block作爲第一個參數。 ..有人可以解釋當對用戶定義類型的引用轉換爲char *時究竟發生了什麼?

+2

這可能是一個壞主意,只是內存轉儲到磁盤,並認爲有後來工作的希望。這可能包含像std :: string這樣的在其他地方存儲數據的指針或結構。嘗試寫一個適當的序列化方法作爲'operator <<',這樣你就可以執行'file << anil'。 – tadman

+2

*本課程是關於編寫和閱讀二進制文件的。* - 啊哈!這個不好的「教訓」在哪裏教授?我問這個問題,因爲這裏有成千上萬的帖子,海報寫這樣的代碼,並且不明白他們的程序爲什麼不起作用。我猜測有人,某本書或某個網站正在將這些信息提供給新手C++編碼人員。 – PaulMcKenzie

+0

我有一種感覺,這是不好的做法。 – ajw170

回答

0

在C/C++,char *經常被用來作爲一種通用類型的數據,因爲它總是指向1個字節。在你的代碼鑄造代碼(char*)&anil獲取指針anil&及管那的指針char秒。它將char s的序列寫入文件,然後將其讀回到anjali的內存中。

這確實一個確切的內存拷貝,如果你有一個指向該內存爲指針別處加載對象回來時,幾乎會永遠有效導致的問題。這可能只是一個示例,但現實世界中的序列化相當棘手,通常最好留給某種序列化庫。手工序列化是可能的,但只能在圖書館或其他地方非常仔細地進行。

如果你想做到這一點的手系列化,你需要確定你的序列化格式和基礎值寫入文件。您還需要確定是否確實需要二進制序列化,或者是否基於文本的序列化更適合。在大多數情況下,將對象寫入像JSON這樣的文件格式會更容易一些,並且還具有語言之間的可移植性和人類可讀性的優點。

+0

我不知道是否鑄造和返回文件,特別是從不同編譯器編譯的不同平臺,可能會導致對齊問題。至少,執行一個'static_cast'。 –

+0

是的,這絕對是可以的。我甚至沒有考慮到不同編譯器可能發生的對齊/排序問題。我可以想象,即使在具有相同編譯器的同一臺機器上,這些問題也可能基於編譯選項發生。但是,無論如何,即使在最簡單的情況下,盲目鑄造'char *'並寫作的方法也可能引發問題。 – danielunderwood

0

std::fstream是從std::istream派生的,基本上是basic_istream<T>char as T的typedef。

所以,fstream::read需要一個字符指針作爲第一個參數並且鑄件轉換的anil起始地址爲char*。自從sizeof(char) == 1在大多數系統中,這是必不可少的字節複製Person實例字節的內容到提供的地址。

這不是長遠來看便攜式也不維護,特別是如果你有指針類中的成員變量,因爲你會基本上是序列化的變量的原始內存地址。

相關問題