boost::serialization:重载load_construct_data:根本没有可访问的构造函数

发布于 2024-11-29 04:27:55 字数 677 浏览 3 评论 0原文

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

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

我尝试简单地调用 create 函数并将 t 设置为等于返回的指针,但是这个似乎不起作用,因为紧接着load_construct_data 函数,并且在序列化函数中,给定的 myClass& 与我设置的“t”不同。

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

so I'm using the boost::serialization library, and I'm trying to overide how a class is constructed, since it has no default constructor. This is demonstrated here. To me it appears the function takes the class* t and then sets it to point to a newly constructed object. If i'm wrong, this is definately the source of my error.

However, the only way to construct my class is by using another classes create() function, meaning I need to stray from the code in the example (this is stated in the boost::serialization namespace): ::new(t)my_class(attribute);

I tried simply calling the create function and setting t equal to the returned pointer, but this doesn't seem to work because right after the load_construct_data function, and in the serialization function, the given myClass& is not the same as what I set 't' to.

How do I do whatever ::new(t) is doing so the object created using the create function follows through into the serialize/other functions?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

铜锣湾横着走 2024-12-06 04:27:55

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

  1. t 必须已经指向已分配的内存区域(默认情况下,new 位置不进行分配)
  2. 在该内存中构造 my_class 的实例地点。

但是,由于在您的情况下您无法使用构造函数,因此不可能使用任何形式的 new 。但还有一种替代方案(某种程度上)。

由于放置 new 几乎只是覆盖一块内存,因此我们可以使用常规函数来对已经构造的对象执行相同的操作。这样的函数是 memcpy

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

所有 memcpy 所做的就是从 source 指向的内存执行 num 个字节的按字节复制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

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

The construct referred to in your question (new(t) my_class(attribute)) is called "placement new". The way it work is that

  1. t must already point to an allocated region of memory (placement new doesn't do allocation by default)
  2. An instance of my_class is constructed at that memory location.

However, since in your case you can't use constructors, then using any form of new is out of the question. But there is an alternative (sort of).

Since placement new pretty much just overwrites a chunk memory, we can use a regular function which does the same with an already constructed object. Such a function is memcpy:

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

All memcpy does is perform a byte-wise copy of num bytes from the memory pointed to by source to the memory pointed to by destination.

So let's say you started with this code in the load_construct_data

my_class obj = other_class::create();

Then we can use the memcpy function to "move" the value at obj into the memory reference by t:

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

While there are some details about how this works with your particular class, such as whether a bit-wise copy is "good enough", this is the best I've got with what you've asked. The one problem I see is if the destructor releases resources, than the copy will may become invalid.

To account for the possible problems with destruction, you can write your own deep copying function:

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

which you call instead of memcpy.

Note: please tell me if I went astray with anything here. I don't currently have a machine to test code on.

云朵有点甜 2024-12-06 04:27:55

在没有默认构造函数的情况下,使用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;
}

In the case of not having a default constructor, the use of load_construct_data and save_construct data actually permits the use of shared_ptr instances. In my view, there is no need to play around with memcpy and raw pointers. Thus you can just do something like the following

#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;
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文