3

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

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

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

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

4

2 回答 2

2

您的问题 ( ) 中提到的构造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复制到指向的内存。numsourcedestination

因此,假设您从以下代码开始load_construct_data

my_class obj = other_class::create();

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

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

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

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

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

你打电话而不是memcpy.

注意:如果我在这里误入歧途,请告诉我。我目前没有机器来测试代码。

于 2011-08-13T12:07:31.193 回答
1

在没有默认构造函数的情况下,使用 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;
}
于 2016-05-05T12:17:15.390 回答