C++中的简单序列化和反序列化
Simple serialization and deserialization in C++
我需要一种方法来序列化不同类型的对象(但派生自同一类的类型),然后将它们反序列化为包含派生类的基类的指针。例如:
#include<iostream>
#include<fstream>
class One
{
public:
int a;
virtual void Func()
{
}
};
class One1: public One
{
char s[128];
void Func1(int l)
{
std::cout<<l<<'n';
}
void Func()
{
Func1(156);
}
};
int main()
{
One* x = new One1;
x->Func();
char* y=(char*)x;
delete x;
/*std::ofstream out("test11.txt",std::ofstream::out | std::ofstream::trunc);
out.write(y,sizeof(One1));
out.close();
std::ifstream in("test11.txt",std::ifstream::in);
char* y1=new char[sizeof(One1)];
in.read(y1,sizeof(One1));*/
One* z=(One*)y/*1*/;
z->Func();
return 0;
}
此代码输出
156
156
但是当我取消注释注释时(当我尝试将对象的 char 表示形式写入文件并从该文件读取时),程序输出156
并在尝试执行z->Func();
时因分段错误而结束。我检查了变量y
的内容是否与y1
不同。为什么?
该问题的原因是什么,我该如何解决它(也许通过使用一些特殊的库)?
1. 不要通过简单地复制字节来序列化派生类
您不能简单地通过将多态对象转换为字节数组,然后通过二进制read
加载它们来编写它们。具有虚函数的类将指向实现的指针存储在 vtable 中。转储派生类的实例将导致转储存储在 vtable 中的指针,在再次运行程序后,该指针不一定是有效的指针。之后访问它很可能会产生分段错误。
如果您确实想使用简单的方法(直接读取和写入字节),请使用 POD 类。
2. 不要访问无效指针
虽然以上是答案中最重要的部分(因为它会完全改变你的程序),但还有其他需要强调的事情。命令:
char* y=(char*)x;
创建指向 x
地址的char
指针。它不会复制对象。因此,当您稍后执行以下操作时:
delete x;
指向y
的指针变为无效。当您稍后尝试将其写入文件时:
std::ofstream out("test11.txt",std::ofstream::out | std::ofstream::trunc);
out.write(y,sizeof(One1));
您访问不属于您的内存。至少现在不是了,因为你明确表示你不需要它,通过早点打电话delete
。
相关文章:
- 如何知道QDataStream不能反序列化某些内容
- 如何使用非默认构造函数实例化模板化类
- 增强基于 XML class_id的反序列化
- 提升反序列化对象具有 nan 或 -nan 值
- 如何在 c++ 非托管代码中反序列化 byte[] 的 json 字符串?
- 使用向量初始化参数化构造函数的对象数组
- 如何反序列化数组?
- 初始化模板化类中的静态 constexpr 成员
- 使用<string>提升::序列化序列化具有 vector<unique_ptr> 成员的类
- 使用 boost::序列化序列化 std::vector of unique_ptr 在 Linux 上失败
- 关于反序列化程序 pop 函数的模板化专用化的歧义
- 使用模板初始化序列数组
- 没有 Boost 的序列化.序列化
- 如何使用 boost::序列化序列化 TAO:<T>:unbouded_basic_string_sequence?
- 使用谷物在库中序列化模板化的多态性类型
- 可从任何序列类型初始化的c++类
- 扩展在if/else序列中初始化的变量的作用域
- 在多线程程序中序列化序列
- 序列化模板化的子类
- 可视化序列化c++类