gpt4 book ai didi

c++ - 在 C++ 中使用指针序列化一个类

转载 作者:太空狗 更新时间:2023-10-29 21:05:30 26 4
gpt4 key购买 nike

我想序列化一个 Person 类型的对象.我想稍后将其用于数据保存甚至游戏保存。我知道如何为 int 这样的基元做这件事, char , bool ,甚至像 char[] 这样的 C 字符串.

问题是,我希望字符串尽可能大而不是声明 char大小为 256 的数组,希望没有人输入太大的东西。我读到用 std::string 序列化一个类作为成员不起作用,因为它有一个内部指针,但是有没有办法序列化我的类,它有一个 char*作为成员(member)?

我知道 Boost 有一个序列化库,但我想在不需要外部库的情况下执行此操作,这似乎是一个值得尝试的好事件。

这是我的 Person类:

class Person
{
private:
char* _fname;
char* _lname;

public:
Person();
Person(const char* fname, const char* lname);
Person(const string& fname, const string& lname);

string fname() const;
void fname(const char* fname);
void fname(const string& fname);

string lname() const;
void lname(const char* lname);
void lname(const string& lname);
};

最佳答案

首先:在你的类中使用 std::string 从长远来看,它会让你的生活变得更加轻松。

但是这个建议对 std::string 和 char* 都有效(有一些显而易见的小调整)。

基本上您想要序列化未知大小的数据(在编译时)。这意味着当您对数据进行反序列化时,您必须有一种技术可以告诉您数据有多长(在对象前加上一个大小),或者有一种方法可以找到数据的结尾(终止标记)。

终止标记更易于序列化。但反序列化更难(因为你必须向前寻找终点)。此外,您必须转义对象中出现的任何终止标记,并且反序列化必须知道转义并将其删除。

因此,由于这种复杂性,我不喜欢使用终止标记。因此,我在对象前加上了一个大小。这样做的代价是我必须以不会破坏的方式对对象的大小进行编码。

因此,如果我们将对象的大小作为前缀,您可以这样做:

// Place a ':' between the string and the size.
// There must be a marker as >> will continue reading if
// fname contains a digit as its first character.
// I don;t like using a space as >> skips spaces if you are not carefull
// and it is hard to tell the start of the string if the first characters in fname
// are the space character.
std::cout << strlen(fname) << ":" << fname;

然后你可以这样反序列化:

size_t size;
char mark;
std::cint >> size >> mark;
if (!std::cin || mark != ':')
{ throw BadDataException;
}
result = new char[size+1](); // Note the () to zero fill the array.
std::cin.read(result, size)

编辑 1(基于评论)更新:与字符串一起使用:

size_t size;
char mark;
std::cint >> size >> mark;
if (!std::cin || mark != ':')
{ throw BadDataException;
}
std::string result(' ', size); // Initialize string with enough space.
std::cin.read(&result[0], size) // Just read directly into the string

编辑 2(基于评论)

序列化字符串的辅助函数

struct StringSerializer
{
std::string& value;
StringSerializer(std::string const& v):value(const_cast<std::string&>(v)){}
friend std::ostream& operator<<(std::ostream& stream, StringSerializer const& data)
{
stream << data.value.size() << ':' << data.value;
}
friend std::istream& operator>>(std::istream& stream, StringSerializer const& data)
{
std::size_t size;
char mark(' ');
stream >> size >> mark;
if (!stream || mark != ':')
{ stream.setstate(std::ios::badbit);
return stream;
}
data.value.resize(size);
stream.read(&data.value[0], size);
}
};

序列化一个人

std::ostream& operator<<(std::ostream& stream, Person const& data)
{
return stream << StringSerializer(data.fname) << " "
<< StringSerializer(data.lname) << " "
<< data.age << "\n";
}
std::istream& operator>>(std::istream& stream, Person& data)
{
stream >> StringSerializer(data.fname)
>> StringSerializer(data.lname)
>> data.age;
std::string line;
std::getline(stream, line);

if (!line.empty())
{ stream.setstate(std::ios::badbit);
}
return stream;
}

用法:

int main()
{
Person p;
std::cin >> p;
std::cout << p;

std::ofstream f("data");
f << p;
}

关于c++ - 在 C++ 中使用指针序列化一个类,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9778806/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com