【问题标题】:boost::serialization: overloading load_construct_data: no accessible constructor at allboost::serialization: 重载 load_construct_data: 根本没有可访问的构造函数
【发布时间】:2011-08-13 11:30:38
【问题描述】:

所以我正在使用 boost::serialization 库,并且我试图覆盖一个类的构造方式,因为它没有默认构造函数。这是demonstrated here。对我来说,该函数似乎采用class* t,然后将其设置为指向一个新构造的对象。如果我错了,这肯定是我的错误的根源。

但是,构造我的类的唯一方法是使用另一个类 create() 函数,这意味着我需要偏离示例中的代码(这在 boost::serialization 命名空间中有所说明):::new(t)my_class(attribute);

我尝试简单地调用创建函数并将t 设置为等于返回的指针,但这似乎不起作用,因为在load_construct_data function 之后和serialization function 中,给定的myClass& 是和我设置的 't' 不一样。

我该如何做 ::new(t) 正在做的事情,以便使用 create 函数创建的对象跟随到序列化/其他函数中?

【问题讨论】:

  • 我认为您的意思是精通而不是足够,但是您实际上并不需要说明这一点-标签中暗示了这一点。
  • 另外,这个问题似乎与boost 无关——我们只需要找到一个替代placement new 以供非构造函数使用。

标签: c++ boost new-operator boost-serialization


【解决方案1】:

您的问题 (new(t) my_class(attribute)) 中提到的构造称为“新位置”。它的工作方式是这样的

  1. t 必须已经指向已分配的内存区域(新位置默认不进行分配)
  2. my_class 的实例在该内存位置构造。

但是,由于在您的情况下您不能使用构造函数,因此使用任何形式的 new 都是不可能的。但是有一个替代方案(有点)。

由于placement new 几乎只是覆盖了一个块内存,我们可以使用一个常规函数来处理已经构建的对象。这样的功能是memcpy:

void * memcpy ( void * destination, const void * source, size_t num );

所有memcpy 所做的只是将num 字节从source 指向的内存复制到destination 指向的内存。

假设您从 load_construct_data 中的这段代码开始

my_class obj = other_class::create();

然后我们可以使用memcpy函数将obj的值“移动”到t的内存引用中:

memcpy((void*)t, (void*)(&obj), sizeof(obj));

虽然有一些关于它如何与您的特定课程一起使用的详细信息,例如按位复制是否“足够好”,但这是我根据您的要求得到的最好的。我看到的一个问题是如果析构函数释放资源,那么副本可能会变得无效。

为了解决销毁可能出现的问题,您可以编写自己的深度复制函数:

void deepCopy( my_class * destination, const my_class * source );

你打电话而不是memcpy。

注意:请告诉我我是否误入歧途。我目前没有可以测试代码的机器。

【讨论】:

  • 非常感谢,经过一周的挫折,你是我的救星!
【解决方案2】:

在没有默认构造函数的情况下,使用 load_construct_data 和 save_construct 数据实际上允许使用 shared_ptr 实例。在我看来,没有必要使用 memcpy 和原始指针。因此,您可以执行以下操作

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

#include <memory>

class MyClass {
  public:
    explicit MyClass(std::string const &str) : m_str(str) {}
    MyClass() = delete;
    std::string str() const
    {
        return m_str;
    }
 private:
   std::string m_str;
};

namespace boost { namespace serialization {

    template<class Archive>
    void serialize(Archive &ar,
                   MyClass const & myClass,
                   unsigned int const) 
    {
        auto str = myClass.str();
        ar & str;
    }

    template<class Archive>
    void save_construct_data(Archive &ar,
                             MyClass const * myClass,
                             unsigned int const)
    {
        auto str = myClass->str();
        ar << str;
    }

    template<class Archive>
    void load_construct_data(Archive &ar,
                             MyClass * myClass,
                             unsigned int const)
    {
        std::string archived;
        ar >> archived;
        ::new(myClass)MyClass(MyClass(archived));
    }
}
}

int main(int argc, const char * argv[]) {

    std::shared_ptr<MyClass> myClass(new MyClass("hello!"));
    std::stringstream os;
    ::boost::archive::text_oarchive oa(os);
    oa << myClass;

    std::shared_ptr<MyClass> myClassB;
    std::stringstream is;
    is.str(os.str());
    ::boost::archive::text_iarchive ia(is);
    ia >> myClassB;

    return 0;
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-01-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多