在内存中修改自身的 C++ 对象

标签 c++

我的一个 friend 和其他人写了下面的代码,根据我的 C++ 知识应该是非常危险的:

Recovery& Recovery::LoadRecoverFile() {
    fstream File("files/recover.dat", ios::in | ios::binary);
    if (File.is_open()) {

        while (!File.eof()) {
            File.read(reinterpret_cast<char*>(this), sizeof(Recovery));  // <----- ?
        }
    }
    File.close();
    return *this; // <----- ?
}

你能告诉我你的意见为什么这是不好的吗?应该如何正确地做到这一点?

他们基本上将 Recovery 类的对象写入文件,并在需要时使用上述方法将其读入。

编辑: 只是为了提供有关代码的一些其他信息。这是 Recovery 类包含的内容。

class Recovery {
public:
    Recovery();
    virtual ~Recovery();
    void createRecoverFile();
    void saveRecoverFile( int level, int win, int credit, gameStates state, int clicks );
    Recovery& LoadRecoverFile();
    const vector<Card>& getRecoverCards() const;
    void setRecoverCards(const vector<Card>& recoverCards);
    int getRecoverClicks() const;
    void setRecoverClicks(int recoverClicks);
    int getRecoverCredit() const;
    void setRecoverCredit(int recoverCredit);
    int getRecoverLevel() const;
    void setRecoverLevel(int recoverLevel);
    gameStates getRecoverState() const;
    void setRecoverState(gameStates recoverState);
    int getRecoverTime() const;
    void setRecoverTime(int recoverTime);
    int getRecoverWin() const;
    void setRecoverWin(int recoverWin);

private:
    int m_RecoverLevel;
    int m_RecoverCredit;
    gameStates m_RecoverState;
};

这会将对象保存到文件中:

void Recovery::saveRecoverFile(int level, int win, int credit, gameStates state,
        int clicks) {

    m_RecoverLevel = level;
    m_RecoverCredit = credit;
    m_RecoverState = state;

    ofstream newFile("files/recover.dat", ios::binary | ios::out);
    if (newFile.is_open()) {
        newFile.write(reinterpret_cast<char*>(this), sizeof(Recovery));
    }

    newFile.close();
}

它的用法是这样的:

    m_Recovery.LoadRecoverFile();
    credit.IntToTextMessage(m_Recovery.getRecoverCredit());
    level.IntToTextMessage(m_Recovery.getRecoverLevel());
    m_cardLogic.setTempLevel(m_Recovery.getRecoverLevel());
    Timer::g_Timer->StartTimer(m_Recovery.getRecoverLevel() + 3);

最佳答案

可能是undefined behavior (除非 Recovery 是仅由标量场组成的 POD)。

如果 Recovery 可能行不通类有一个 vtable ,除非正在读取的进程可能与写入它的进程相同。 Vtable 包含函数指针(通常是一些机器代码的地址)。并且这些函数指针会因一个进程而异(即使它们运行相同的二进制文件),例如因为ASLR .

如果 Recovery 也行不通包含其他对象(例如 std::vector<std::shared_ptr<Recovery>> ....,或您的 gameStates ),因为这些子对象将无法正确构造。

有时它可以工作。但是您显然正在寻找的是 serialization (然后我建议使用像 JSON 这样的文本格式,但另请参阅 libs11n )或 application checkpointing .您应该从一开始就以这些目标设计您的应用程序。

关于在内存中修改自身的 C++ 对象,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26550235/

相关文章:

c++ - 树莓派SFML播放音频

c++ - 将数据的平均值插入 vector

c# - Visual Studio 扩展 (VSIX/DLL) 到一个 exe

c++ - 如何告诉git我的本地目录是远程树中的特定目录

c# - 使用函数指针的好处

c++ - 错误的 'for' 循环结果 C++

c++ - 在C++中将数组中的所有数字相加

c++ - 具有某些不会在逻辑上定义的属性的类的概念

c++ - 显式类模板实例化的链接

c++ - GCC 5 的模板参数阴影