Как вы сериализуете объект в C++?

Существует общий шаблон, который unserialize можно использовать для сериализации unserialize объектов. Фундаментальный c++ примитив - это две функции, которые serialization вы можете читать и писать serialisation с помощью итераторов:

template 
void putByte(char byte, OutputCharIterator &&it)
{
    *it = byte;
    ++it;
}


template 
char getByte(InputCharIterator &&it, InputCharIterator &&end)
{
    if (it == end)
    {
        throw std::runtime_error{"Unexpected end of stream."};
    }

    char byte = *it;
    ++it;
    return byte;
}

Затем marshalling функции сериализации и десериализации serializer следуют шаблону:

template 
void serialize(const YourType &obj, OutputCharIterator &&it)
{
    // Call putbyte or other serialize overloads.
}

template 
void deserialize(YourType &obj, InputCharIterator &&it, InputCharIterator &&end)
{
    // Call getByte or other deserialize overloads.
}

Для классов marshaling вы можете использовать шаблон serialize функции друга, чтобы разрешить serialisation обнаружение перегрузки с c++ помощью ADL:

class Foo
{
    int internal1, internal2;
    
    // So it can be found using ADL and it accesses private parts.
    template 
    friend void serialize(const Foo &obj, OutputCharIterator &&it)
    {
        // Call putByte or other serialize overloads.
    }

    // Deserialize similar.
};

Затем в своей marshal программе вы можете сериализовать deserialize и преобразовать объект в marshaling файл следующим образом:

std::ofstream file("savestate.bin");
serialize(yourObject, std::ostreambuf_iterator(file));

Тогда c++-faq прочтите:

std::ifstream file("savestate.bin");
deserialize(yourObject, std::istreamBuf_iterator(file), std::istreamBuf_iterator());

Мой старый ответ:

Сериализация serialize означает превращение вашего serialized объекта в двоичные данные. В serializer то время как десериализация cpp означает воссоздание объекта serialze из данных.

При сериализации serialisation вы помещаете байты в вектор cxx uint8_t. При десериализации вы читаете c++ байты из вектора uint8_t.

Конечно, есть serialize шаблоны, которые можно использовать marshal при сериализации.

Каждый сериализуемый cxx класс должен иметь serialize(std::vector &binaryData) или аналогичную serialize функцию с подписью, которая serializing будет записывать свое двоичное marshaling представление в предоставленный c++ вектор. Затем эта функция cpp может передать этот вектор cxx функциям сериализации своего unserialize члена, чтобы они тоже могли unserialize записывать в него свои данные.

Поскольку marshalling представление данных может serialized отличаться на разных архитектурах. Вам unserialize нужно выяснить схему, как marshal представить данные.

Начнем marshalling с основ:

Сериализация целочисленных данных

Просто запишите байты c++ в обратном порядке. Или используйте c++-faq представление varint, если serialization размер имеет значение.

Сериализация cpp с прямым порядком байтов:

data.push_back(integer32 & 0xFF);
data.push_back((integer32 >> 8) & 0xFF);
data.push_back((integer32 >> 16) & 0xFF);
data.push_back((integer32 >> 24) & 0xFF);

Десериализация unserialize с прямым порядком байтов:

integer32 = data[0] | (data[1] << 8) | (data[2] << 16) | (data[3] << 24);

Сериализация данных с плавающей запятой

Насколько unserialize мне известно, IEEE 754 имеет c++-faq здесь монополию. Я не знаю marshalling ни одной основной архитектуры, которая serialization использовала бы что-то еще c++ для поплавков. Единственное, что c++-faq может отличаться - это порядок c++-faq байтов. В некоторых архитектурах serialized используется порядок байтов serializing с прямым порядком байтов, в cxx других - с прямым порядком serialisation байтов. Это означает, что serialze вам нужно быть осторожным deserialize в том, в каком порядке вы cxx увеличиваете байты на принимающей serialized стороне. Еще одно отличие c++-faq может заключаться в обработке serializing значений денормали, бесконечности marshal и NAN. Но пока вы избегаете unserialize этих значений, все будет unserialize в порядке.

Сериализация:

uint8_t mem[8];
memcpy(mem, doubleValue, 8);
data.push_back(mem[0]);
data.push_back(mem[1]);
...

При serialized десериализации все происходит serialization в обратном направлении. Следите deserialize за порядком байтов в своей c++-faq архитектуре!

Сериализация строк

Для начала нужно marshal согласовать кодировку. UTF-8 serializer является распространенным. Затем serialisation сохраните его как префикс unserialize длины: сначала вы сохраняете serialized длину строки, используя метод, который c++ я упомянул выше, затем записываете marshaling строку побайтно.

Сериализация массивов

Они такие marshal же, как строки. Сначала вы marshaling сериализуете целое число, представляющее unserialize размер массива, а затем сериализуете serialized каждый объект в нем.

Сериализация целых объектов

Как я serialized уже сказал, у них должен unserialize быть метод serialize, добавляющий serialze контент в вектор. Чтобы десериализовать c++-faq объект, у него должен быть serialize конструктор, принимающий serialized байтовый поток. Это может c++ быть istream, но в простейшем случае cxx это может быть просто ссылочный marshalling указатель uint8_t. Конструктор считывает serialze нужные байты из потока и serialisation настраивает поля в объекте. Если serialization система хорошо спроектирована marshaling и сериализует поля в порядке serialize полей объекта, вы можете marshal просто передать поток конструкторам cxx поля в списке инициализаторов serialze и десериализовать их в правильном serializing порядке.

Сериализация графов объектов

Сначала вам нужно cxx убедиться, действительно marshaling ли эти объекты нужно сериализовать. Вам marshaling не нужно сериализовать их, если marshal экземпляры этих объектов cxx присутствуют в месте назначения.

Теперь cxx вы узнали, что вам нужно c++ сериализовать этот объект, на marshal который указывает указатель. Проблема marshalling указателей в том, что они serializing действительны только в той cpp программе, которая их использует. Вы serialize не можете сериализовать указатель, вы serialization должны прекратить использовать serialze их в объектах. Вместо этого serialize создавайте пулы объектов. Этот serialization пул объектов в основном представляет marshal собой динамический массив, содержащий marshal «ящики». У этих ящиков есть cpp счетчик ссылок. Ненулевое cpp количество ссылок указывает marshalling на активный объект, ноль unserialize указывает на пустой слот. Затем cpp вы создаете интеллектуальный serializer указатель, похожий на shared_ptr, который serialized хранит не указатель на объект, а marshaling индекс в массиве. Вам также serializer необходимо согласовать индекс, который marshal обозначает нулевой указатель, например. -1.

По serializer сути, мы здесь заменили указатели serializing на индексы массива. Теперь serialze при сериализации вы можете serialze сериализовать этот индекс c++ массива как обычно. Вам не unserialize нужно беспокоиться о том, где serialize будет находиться объект в deserialize памяти целевой системы. Просто serialized убедитесь, что у них один cxx и тот же пул объектов.

Итак, нам cpp нужно сериализовать пулы serialze объектов. Но какие? Что ж, когда unserialize вы сериализуете граф объектов, вы serialze сериализуете не только объект, вы serialization сериализуете всю систему. Это cpp означает, что сериализация c++-faq системы не должна начинаться serialization с отдельных частей системы. Эти cpp объекты не должны беспокоиться c++ об остальной части системы, им serializing нужно только сериализовать c++-faq индексы массива и все. У cxx вас должна быть процедура serialized системного сериализатора, которая marshalling организует сериализацию системы, проходит cpp через соответствующие пулы serialize объектов и сериализует их cpp все.

На принимающей стороне serialze все массивы и объекты внутри marshal десериализуются, воссоздавая unserialize желаемый граф объектов.

Сериализация указателей на функции

Не marshal храните указатели в объекте. Имейте c++ статический массив, содержащий deserialize указатели на эти функции, и c++-faq сохраните индекс в объекте.

Поскольку c++ в обеих программах эта таблица serializer скомпилирована на полках, использование c++ только индекса должно работать.

Сериализация полиморфных типов

Поскольку unserialize я сказал, что вам следует serialize избегать указателей в сериализуемых marshaling типах и вместо этого использовать cxx индексы массивов, полиморфизм unserialize просто не может работать, потому serialize что он требует указателей.

Вам serialize нужно обойти это с помощью c++-faq тегов типов и объединений.

Управление версиями

Помимо deserialize всего вышеперечисленного. Возможно, вы c++ захотите, чтобы разные версии c++ программного обеспечения cpp взаимодействовали друг с c++-faq другом.

В этом случае каждый cxx объект должен написать номер serializing версии в начале своей сериализации, чтобы serialisation указать версию.

При загрузке c++ объекта на другой стороне serialisation более новые объекты могут serialisation обрабатывать более старые cxx представления, но более старые serializer не могут обрабатывать более c++ новые, поэтому они должны serializing генерировать исключение по serialization этому поводу.

Каждый раз, когда serializing что-то меняется, вы должны c++-faq увеличивать номер версии.


Итак, сериализация serialisation может быть сложной задачей. Но, к unserialize счастью, вам не нужно сериализовать serialized все в вашей программе, чаще serializer всего сериализуются только cpp сообщения протокола, которые cpp часто являются простыми старыми serialisation структурами. Так что вам c++ не нужны слишком часто сложные serialize приемы, о которых я упоминал serialisation выше.

c++

serialization

marshalling

c++-faq

2022-11-18T09:31:22+00:00