Могу ли я сериализовать класс, приведя его к типу char * - PullRequest
0 голосов
/ 15 января 2020

В C ++ можно ли преобразовать класс или некоторые данные в void*, а затем в char* для сериализации? Если так, как бы я десериализовал? Меня не особо волнует переносимость

class t{
public:
  uint8_t data[32][32][32]
}
t temp;
temp.data = something;
char* serialized = (char*)(void*)&temp;//????

Ответы [ 3 ]

1 голос
/ 15 января 2020

Это не путь к go.

В каких условиях это может работать?

В лучшем случае для типа, который не содержит указателя и который дополнительно содержит тривиально копируемый тип , вы действительно могли бы написать байтов по адресу памяти объекта в файл, и перезагрузите данные безопасно позже.

Но приведение недостаточно: приведение к char* позволяет вам записывать или копировать необработанные данные куда-либо. Но только если вы также знаете размер объекта. Один указатель не несет эту информацию о длине.

Для успешной десериализации вам потребуется не только прочитать размер данных и их необработанное содержимое. Но вам также необходимо знать класс, чтобы создать объект перед загрузкой его необработанных данных. Это подразумевает, что вы также пишете информацию о типе объекта и что ваша функция десериализации может справиться с этой информацией.

Почему в общем случае произойдет сбой?

Конечно, это очень Подход basi c сериализации / десериализации потерпит неудачу, как только у вас будет более сложный класс. Например:

  • Если у вас нетривиальный конструктор или оператор присваивания, эта тактика десериализации c не может гарантировать, что ваши структуры данных остаются согласованными. Например, если конструктор или оператор присваивания будет поддерживать некоторый вид подсчета объекта stati c, он будет не синхронизирован c после десериализации.
  • Как только у вас есть указатель или нетривиально копируемый объект-член, вы можете поспорить, что все необходимые данные не обязательно являются смежными. Таким образом, ваше написание объекта будет записывать только часть необходимых данных. Кроме того, значения указателя действительны только в текущем процессе. Если вы читаете его в другом процессе (другой программе или той же программе, которая была запущена в другой день), значение указателя бесполезно.

Другими словами, в большинстве случаев ваша программа будет UB.

Как правильно это сделать?

Сериализацию правильно выполнить не сложно. Во-первых, есть множество библиотек, которые выполняют большую часть работы за вас.

Но вы можете легко написать это сами: вам просто нужно иметь функцию save() в каждом сериализуемом классе: объекты будут сериализовывать себя, так как они лучше знают, что должно быть написано! Каждый класс также имеет фабрику stati c с функцией load(), которая способна создать новый объект и заполнить его данными.

1 голос
/ 15 января 2020

Если класс POD (Plain Old Data), то, возможно,. Обычно это не так, поэтому вам нужно сериализовать вручную. Например, любой класс, который содержит указатели прямо или косвенно (скажем, путем включения объектов, содержащих указатели, такие как std :: string), не может быть автоматически сериализован в массив. У вас также есть разные выравнивания памяти между различными системами.

Связанный: Что такое типы POD в C ++?

0 голосов
/ 15 января 2020

«Могу ли я сериализовать класс, приведя его к типу char *» - в общем; Нет .

Невозможно сериализовать / десериализовать, используя материал. Приведение не конвертирует ничего, оно просто меняет способ просмотра / интерпретации данных компилятором.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...