无法使C ++ Boost指针序列化工作

时间:2015-03-06 15:05:37

标签: c++ serialization boost

此问题与列为重复的问题不同: Boost c++ serializing a char * 我没有使用shared_ptr,而且我可以完全访问我的类的内部。

我能找到的最接近的响应是Store a vector of pointers to custom objects to file,我通过搜索编译错误找到了。

然而,那里给出的答案并不清楚,至少对我没有。它指向提升文档,这表明我在这里列出的简单代码应该可行。在对通过指针序列化对象的所有内务编目进行编目之后,增强文档会说明这一点。

  

此序列化库解决了上述所有注意事项。

如果我必须一次写一个char []一个字符,或者我必须取消引用容器中的所有指针对象并将它们分解为它们的组成POD部分,先将它们的大小以字节为单位写入流中使用boost进行序列化,然后使用boost似乎没什么意义。这是最重要的工作。创建文本输出流并将字节喷入其中是微不足道的。

我不是说我可能对文档有阅读理解问题,但是根据我对我读过的内容的理解,下面的代码片段应该有效。但是,此代码会发出以下编译器错误。所以,我必须省略一些东西,但我看不到它,所以这就是我寻求帮助的原因。

如何简单地指出下面代码段中的失败点?或者,更好的是,提供一个可行的片段?

/usr/include/boost/serialization/access.hpp:118:9: error: ‘class boost::ptr_vector<std::basic_string<char> >’ has no member named ‘serialize’
         t.serialize(ar, file_version);
         ^
#include <fstream>
#include <boost/archive/text_oarchive.hpp>
#include <boost/archive/text_iarchive.hpp>

class A {
public:
        A(){}

        char c;
        char *name;

        friend boost::serialization::access;
        template<class Archive>

        void serialize(Archive& ar, unsigned version) 
        {
                ar &  name;
        }
};

main()
{
        A a;
        a.name = (char *)"this is a test";

        std::ofstream ofs("table.txt");
        boost::archive::text_oarchive os(ofs);
        os << a;
}

我可以序列化int,char,甚至STL类型,但是我不能用指针序列化任何东西。例如,我可以序列化std::vector<std::string>,但如果我尝试序列化std::vector<std::string *>,我将得到编译器错误。

1 个答案:

答案 0 :(得分:1)

  

如果我必须一次写一个char []一个字符,或者我必须取消引用容器中的所有指针对象并将它们分解为它们的组成POD部分,先将它们的大小以字节为单位写入流中使用boost进行序列化,然后使用boost似乎没什么意义。

是。但是你正在尝试序列化指针。指向char的指针应该序列化为什么?当然T*应序列化动态分配的T,不是吗?因此,除非charname,否则您希望序列化单个nullptr

或者您希望对序列化的每个字符进行完整的对象跟踪吗?

这里的重点是你选择了一个原始类型的原始指针。指针缺少必要的信息。因此,您有责任添加信息。如果您发现乏味,则可以自由使用C ++类型。

顺便说一句,请注意,这在C ++ 03及以上版本中是不合法的:

a.name = (char *)"this is a test";

char const(&)[15]char *的静态强制转换会丢弃const限定条件。无论如何,您的编译器应拒绝此代码。

这是我对它的看法(使用std::string):

#include <boost/serialization/string.hpp>
#include <boost/archive/text_oarchive.hpp>

class A {
  public:
    std::string name;
    template <class Archive> void serialize(Archive &ar, unsigned) {
        ar & name;
    }
};

int main() {
    A a { "this is a test" };
    boost::archive::text_oarchive os(std::cout);
    os << a;
}

顺便提一下,链接的重复问题的标题与您在此处尝试的内容完全匹配: Boost c++ serializing a char * ,并且接受的答案显示完全相同的解决方案。

如果你真的坚持,你当然可以去捣乱一些C风格的代码而不用荣耀:

#include <boost/serialization/serialization.hpp>
#include <boost/serialization/binary_object.hpp>
#include <boost/archive/text_oarchive.hpp>
#include <cstring>
#include <cstdlib>

class A {
  public:
    A(char const* sz = nullptr) : name(sz? strdup(sz) : nullptr) {}
    A(A const&) = delete;
    A& operator=(A const&) = delete;

    ~A() { free(name); }

  private:
    char* name;

    template <class Archive> void save(Archive &ar, unsigned) const {
        bool have_name = name;
        ar & have_name;

        if (have_name)
        {
            size_t len = strlen(name);
            ar & len;
            ar & boost::serialization::make_binary_object(name, len);
        }
    }

    template <class Archive> void load(Archive &ar, unsigned) {
        bool have_name = name;
        ar & have_name;

        if (!have_name)
        {
            free(name);
            name = nullptr;
        } else
        {
            size_t len = 0;
            ar & len;

            name = static_cast<char*>(realloc(name, len));
            ar & boost::serialization::make_binary_object(name, len);
        }
    }

    friend class boost::serialization::access;
    BOOST_SERIALIZATION_SPLIT_MEMBER()
};


int main() {
    A a { "this is a test" };
    boost::archive::text_oarchive os(std::cout);
    os << a;
}

但是所有这些都会让你获得6倍的代码,贬低的价值语义,完全放弃关注点分离,潜在的bug很多(你是否认为有name==nullstrlen(name)==0之间的区别?目前我的实施employs unspecified (implementation-defined) behaviour。我将把它作为练习留给你,读者,在这里提出密封处理)和......甚至不能读取字符串输出。

  

是的,当然make_array会给你14 116 104 105 115 32 105 115 32 97 32 116 101 115 116而不是dGhpcyBpcyBhIHRlc3Q=,但那可怕的存储效率低,而且仍然不是人类可读的。