我不是 C++ 专家,但我过去已经连载过几次。不幸的是,这次我试图序列化一个包含 std::string 的类,我理解这与序列化指针非常相似。
我可以将类写入文件并再次读回。所有 int
字段都很好,但 std::string
字段给出“地址越界”错误,大概是因为它指向不再存在的数据。
对此有标准的解决方法吗?我不想回到 char 数组,但至少我知道它们在这种情况下可以工作。如果需要,我可以提供代码,但我希望我已经很好地解释了我的问题。
我通过将类转换为 char*
并使用 std::fstream
将其写入文件来进行序列化。读书当然正好相反。
I'm not a c++ expert but I've serialized things a couple of times in the past. Unfortunately this time I'm trying to serialize a class which contains an std::string
, which I understand is pretty much like serializing a pointer.
I can write out the class to a file and read it back in again. All int
fields are fine, but the std::string
field gives an "address out of bounds" error, presumably because it points to data which is no longer there.
Is there a standard workaround for this? I don't want to go back to char
arrays, but at least I know they work in this situation. I can provide code if necessary, but I'm hoping I've explained my problem well.
I'm serializing by casting the class to a char*
and writing it to a file with std::fstream
. Reading of course is just the reverse.
发布评论
评论(6)
不幸的是,这只有在不涉及指针的情况下才有效。您可能想要为您的类提供
void MyClass::serialize(std::ostream)
和void MyClass::deserialize(std::ifstream)
,并调用它们。对于这种情况,您可能还希望重载流运算符以便于使用。
Unfortunately, this only works as long as there are no pointers involved. You might want to give your classes
void MyClass::serialize(std::ostream)
andvoid MyClass::deserialize(std::ifstream)
, and call those. For this case, you'd wantYou may also want to overload the stream operators for easier use.
简单地将对象的二进制内容写入文件不仅不可移植,而且正如您所认识到的那样,对于指针数据也不起作用。您基本上有两个选择:要么编写一个真正的序列化库,它可以通过使用 c_str() 将实际字符串输出到文件,或者您使用优秀的 Boost 序列化 库。如果可能的话,我建议使用后者,然后您可以使用如下简单代码进行序列化:
这里,函数
serialize
用于序列化和反序列化数据,具体取决于您如何调用它。请参阅文档以获取更多信息。Simply writing the binary contents of an object into a file is not only unportable but, as you've recognized, doesn't work for pointer data. You basically have two options: either you write a real serialization library, which handles std::strings properly by e.g. using c_str() to output the actual string to the file, or you use the excellent boost serialization library. If at all possible, I'd recommend the latter, you can then serialize with a simple code like this:
Here, the function
serialize
works for serializing and deserializing the data, depending on how you call it. See the documentation for more information.对于字符串或其他大小可变的 blob,最简单的序列化方法是在序列化整数时首先序列化大小,然后将内容复制到输出流。
读取时,首先读取大小,然后分配字符串,然后通过从流中读取正确的字节数来填充它。
另一种方法是使用分隔符和转义,但需要更多代码,并且序列化和反序列化速度较慢(但结果可以保持人类可读)。
The easiest serialization method for strings or other blobs with variable size is to serialize first the size as you serialize integers, then just copy the content to the output stream.
When reading you first read the size, then allocate the string and then fill it by reading the correct number of bytes from the stream.
An alternative is to use a delimiter and escaping, but requires more code and is slower both on serialization and deserialization (however the result can be kept human readable).
如果您的类包含任何外源数据(
string
)。您对于出现分段错误的原因是正确的。我将创建一个成员函数,该函数将采用
fstream
并从中读取数据,以及一个反函数,该函数将采用fstream
并将其内容写入其中稍后恢复,如下所示:您还可以定义
operator<<
和operator>>
来与istream
和ostream 一起使用
进行序列化和如果您想要语法糖,也可以恢复您的课程。You'll have to use a more complicated method of serialization than casting a class to a
char*
and writing it to a file if your class contains any exogenous data (string
does). And you're correct about why you're getting a segmentation fault.I would make a member function that would take an
fstream
and read in the data from it as well as an inverse function which would take anfstream
and write it's contents to it to be restored later, like this:You can also define
operator<<
andoperator>>
to work withistream
andostream
to serialize and restore your class as well if you want that syntactic sugar.为什么不只是类似以下内容:
然后:
Why not just something along the lines of:
and then: