序列化包含 std::string 的类

新手上路,请多包涵

我不是 C++ 专家,但过去我已经序列化了几次。不幸的是,这次我试图序列化一个包含 std::string 的类,我理解这很像序列化指针。

我可以把类写到一个文件中,然后再读回来。所有 int 字段都很好,但 std::string 字段给出“地址越界”错误,可能是因为它指向的数据不再存在。

有没有标准的解决方法?我不想回到 char 数组,但至少我知道它们在这种情况下工作。如有必要,我可以提供代码,但我希望我已经很好地解释了我的问题。

我通过将类转换为 char* 并将其写入带有 std::fstream 的文件来进行序列化。阅读当然正好相反。

原文由 iwasinnamuknow 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 681
2 个回答

我通过将类转换为 char* 并使用 fstream 将其写入文件来进行序列化。阅读当然正好相反。

不幸的是,这仅在不涉及指针的情况下才有效。你可能想给你的课程 void MyClass::serialize(std::ostream)void MyClass::deserialize(std::ifstream) ,然后打电话给他们。对于这种情况,您需要

std::ostream& MyClass::serialize(std::ostream &out) const {
    out << height;
    out << ',' //number seperator
    out << width;
    out << ',' //number seperator
    out << name.size(); //serialize size of string
    out << ',' //number seperator
    out << name; //serialize characters of string
    return out;
}
std::istream& MyClass::deserialize(std::istream &in) {
    if (in) {
        int len=0;
        char comma;
        in >> height;
        in >> comma; //read in the seperator
        in >> width;
        in >> comma; //read in the seperator
        in >> len;  //deserialize size of string
        in >> comma; //read in the seperator
        if (in && len) {
            std::vector<char> tmp(len);
            in.read(tmp.data() , len); //deserialize characters of string
            name.assign(tmp.data(), len);
        }
    }
    return in;
}

您可能还希望重载流运算符以便于使用。

 std::ostream &operator<<(std::ostream& out, const MyClass &obj)
{obj.serialize(out); return out;}
std::istream &operator>>(std::istream& in, MyClass &obj)
{obj.deserialize(in); return in;}

原文由 Mooing Duck 发布,翻译遵循 CC BY-SA 3.0 许可协议

简单地将对象的二进制内容写入文件不仅不可移植,而且正如您所认识到的,它不适用于指针数据。您基本上有两个选择:或者您编写一个真正的序列化库,通过例如使用 c_str() 将实际字符串输出到文件来正确处理 std::strings,或者您使用出色的 boost 序列化 库。如果可能的话,我会推荐后者,然后您可以使用这样的简单代码进行序列化:

 #include <boost/archive/text_iarchive.hpp>
#include <boost/archive/text_oarchive.hpp>
#include <boost/serialization/string.hpp>

class A {
    private:
        std::string s;
    public:
        template<class Archive>
        void serialize(Archive& ar, const unsigned int version)
        {
            ar & s;
        }
};

在这里,函数 serialize 用于序列化和反序列化数据,具体取决于您如何调用它。有关更多信息,请参阅文档。

原文由 Antti 发布,翻译遵循 CC BY-SA 3.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题