Повысить сериализацию c ++ с ++ - PullRequest
5 голосов
/ 23 февраля 2011

У меня есть класс, и я пытаюсь сериализовать shared_ptr, но обычный метод сериализации объекта не работает:

class Object {
public:
    Object();
    ~Object();

    shared_ptr<char>objectone;

    friend class boost::serialization::access;
    template <typename Archive>
    void serialize(Archive &ar, const unsigned int version)
    {
        ar & objectone;
    }
};

Я даже пытался сделать это таким образом, но он все еще не 't работа:

    void serialize(Archive &ar, const unsigned int version)
    {
        for (int i = 0; i < (strlen(objectone.get())); i++)
             ar & objectone.get()[i];
    }

Есть идеи, как подойти к этому?Спасибо.

Дополнительная информация:

Я уже включил оба заголовочных файла shared_ptr:

#include <boost/serialization/shared_ptr.hpp>
#include <boost/serialization/shared_ptr_132.hpp>

Я попытался преобразовать в строку и сериализовать ее втаким образом, но выдает следующую ошибку: boost :: archive :: archive_exception 'what (): ошибка потока

friend class boost::serialization::access;
template <typename Archive>
void serialize(Archive &ar, const unsigned int version)
{
    if (objectone.get()) {
        string temp(objectone.get());
        ar & temp;
    }
    ar & objectone;
}

Ответы [ 3 ]

4 голосов
/ 23 февраля 2011

Имейте в виду, что Сумасшедший Эдди сказал, что shared_ptr не является подходящим инструментом для работы.Поскольку у вас нет возможности изменить определение класса, здесь есть обходной путь.

boost :: serialization предоставляет оболочку make_array , которая принимает указатель и упаковывает его в массивдля сериализации.Это требует, чтобы размер массива был известен до сериализации.

Затем вы могли бы сделать что-то вроде:

void serialize(Archive &ar, const unsigned int version)
{
    ar & array_size; // Figure out how to determine this (perhaps strlen(objectone.get())

    if (ar::is_loading)
    {
        objectone.reset(new char[array_size]); // allocate the array before we load it
    }

    if (objectone.get() != NULL)
    {
        ar & make_array(objectone.get(), array_size);
    }
}

Этот пример кода довольно прост, но передает концепцию.

4 голосов
/ 23 февраля 2011

В вашем коде больше, чем одна проблема.

Во-первых, shared_ptr не предназначен для хранения массивов. Хватит это делать.

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

Если вы действительно настаиваете на сохранении строки char*, вам необходимо преобразовать ее в vector/string и сохранить ее. Затем после прочтения вам нужно прочитать обратно vector/string, получить размер, выделить память, вставить ее в ... и т. Д. Отслеживание указателей не сработает, поэтому, если вы полагаетесь на это, у вас будет реализовать это самостоятельно. Веселитесь.

Новое редактирование кода:

Вы делаете бит сохранения в функции, которая охватывает как сохранение, так и загрузку. Конечно, это не очень хорошо работает при загрузке. Вам нужно разделить вашу сериализацию. if (Archive::is_saving) тоже не сработает. В документации повышения объясняется, как правильно разделить процедуру сериализации.

2 голосов
/ 23 февраля 2011

Вам не хватает некоторых ключевых понятий.Вам больше не нужен share_ptr, если вы используете std :: string.

Вы можете сделать

class Object {
public:
    Object();
    ~Object();

    std::string name;

    template <typename Archive>
    void serialize(Archive &ar, const unsigned int version)
    {
        ar & name;
    }
};

и все готово.

Добавление

Учитывая ваши требования, это то, что вам нужно сделать

class test
{
public:

friend class boost::serialization::access;

test() 
{       
}

template<class Archive>
void save(Archive & ar, const unsigned int version) const
{
    int len = strlen(data.get());
    ar  & len;
    for (int index = 0; index < len; ++index)
        ar & data[index];       
}
template<class Archive>
void load(Archive & ar, const unsigned int version)
{
    int len = 0;
    ar  & len;
    data = boost::shared_array<char>(new char[len+1]);
    for (int index = 0; index < len; ++index)
        ar & data[index];
    data[len] = 0;
}
BOOST_SERIALIZATION_SPLIT_MEMBER()

boost::shared_array<char> data;
};
...