Boost::进程间容器容器调整大小无默认构造函数

发布于 2024-08-29 05:14:15 字数 3399 浏览 10 评论 0原文

在梳理了 Boost::Interprocess 文档和 Google 搜索后,我想我已经找到了问题的原因/解决方法。据我所知,我发现的一切似乎都在暗示这一点,但并没有出来说“这样做是因为……”。但如果有人能证实这一点,我将不胜感激。

我正在编写一系列类,这些类表示存储在内存中的大量信息查找,以便在并行应用程序中实现快速性能。由于数据的大小和在一台机器上同时运行的多个进程,我们使用 Boost::Interprocess 共享内存来拥有结构的单个副本。

我查看了 Boost::Interprocess 文档和示例,它们为共享内存字符串、字符串向量、int 向量向量等键入了 typedef 类。当他们在示例中“使用”它们时,他们只是通过分配器来构造它们,也许插入他们在其他地方构建的一项。就像这个页面一样: http://www.boost .org/doc/libs/1_42_0/doc/html/interprocess/allocators_containers.html

因此,按照他们的示例,我为共享内存类创建了一个带有 typedef 的头文件:

namespace shm {
    namespace bip = boost::interprocess;

    // General/Utility Types
    typedef bip::managed_shared_memory::segment_manager segment_manager_t;
    typedef bip::allocator<void, segment_manager_t> void_allocator;

    // Integer Types
    typedef bip::allocator<int, segment_manager_t> int_allocator;
    typedef bip::vector<int, int_allocator> int_vector;

    // String Types
    typedef bip::allocator<char, segment_manager_t> char_allocator;
    typedef bip::basic_string<char, std::char_traits<char>, char_allocator> string;
    typedef bip::allocator<string, segment_manager_t> string_allocator;
    typedef bip::vector<string, string_allocator> string_vector;
    typedef bip::allocator<string_vector, segment_manager_t> string_vector_allocator;
    typedef bip::vector<string_vector, string_vector_allocator> string_vector_vector;
}

然后对于我的一个查找表类,它被定义像这样的:

class Details {
public:
    Details(const shm::void_allocator & alloc) :
        m_Ids(alloc),
        m_Labels(alloc),
        m_Values(alloc) {
    }
    ~Details() {}

    int Read(BinaryReader & br);

private:
    shm::int_vector m_Ids;
    shm::string_vector m_Labels;
    shm::string_vector_vector m_Values;
};

int Details::Read(BinaryReader & br) {
    int num = br.ReadInt();

    m_Ids.resize(num);
    m_Labels.resize(num);
    m_Values.resize(num);

    for (int i = 0; i < num; i++) {
        m_Ids[i] = br.ReadInt();
        m_Labels[i] = br.ReadString().c_str();

        int count = br.ReadInt();
        m_Value[i].resize(count);
        for (int j = 0; j < count; j++) {
            m_Value[i][j] = br.ReadString().c_str();
        }
    }
}

但是当我编译它时,我收到错误: 'boost::interprocess::allocator::allocator':没有合适的默认构造函数可用

这是由于对向量对象的resize()调用造成的。因为allocator类型没有空构造函数(它们采用const segment_manager_t &),并且它尝试为每个位置创建一个默认对象。因此,为了使其工作,我必须获取一个分配器对象并在 resize 上传递一个默认值对象。像这样:

int Details::Read(BinaryReader & br) {
    shm::void_allocator alloc(m_Ids.get_allocator());
    int num = br.ReadInt();

    m_Ids.resize(num);
    m_Labels.resize(num, shm::string(alloc));
    m_Values.resize(num, shm::string_vector(alloc));

    for (int i = 0; i < num; i++) {
        m_Ids[i] = br.ReadInt();
        m_Labels[i] = br.ReadString().c_str();

        int count = br.ReadInt();
        m_Value[i].resize(count, shm::string(alloc));
        for (int j = 0; j < count; j++) {
            m_Value[i][j] = br.ReadString().c_str();
        }
    }
}

这是最好/正确的方法吗?或者我错过了什么。

谢谢!

After combing through the Boost::Interprocess documentation and Google searches, I think I've found the reason/workaround to my issue. Everything I've found, as I understand it, seems to be hinting at this, but doesn't come out and say "do this because...". But if anyone can verify this I would appreciate it.

I'm writing a series of classes that represent a large lookup of information that is stored in memory for fast performance in a parallelized application. Because of the size of data and multiple processes that run at a time on one machine, we're using Boost::Interprocess for shared memory to have a single copy of the structures.

I looked at the Boost::Interprocess documentation and examples, and they typedef classes for shared memory strings, string vectors, int vector vectors, etc. And when they "use" them in their examples, they just construct them passing the allocator and maybe insert one item that they've constructed elsewhere. Like on this page: http://www.boost.org/doc/libs/1_42_0/doc/html/interprocess/allocators_containers.html

So following their examples, I created a header file with typedefs for shared memory classes:

namespace shm {
    namespace bip = boost::interprocess;

    // General/Utility Types
    typedef bip::managed_shared_memory::segment_manager segment_manager_t;
    typedef bip::allocator<void, segment_manager_t> void_allocator;

    // Integer Types
    typedef bip::allocator<int, segment_manager_t> int_allocator;
    typedef bip::vector<int, int_allocator> int_vector;

    // String Types
    typedef bip::allocator<char, segment_manager_t> char_allocator;
    typedef bip::basic_string<char, std::char_traits<char>, char_allocator> string;
    typedef bip::allocator<string, segment_manager_t> string_allocator;
    typedef bip::vector<string, string_allocator> string_vector;
    typedef bip::allocator<string_vector, segment_manager_t> string_vector_allocator;
    typedef bip::vector<string_vector, string_vector_allocator> string_vector_vector;
}

Then for one of my lookup table classes, it's defined something like this:

class Details {
public:
    Details(const shm::void_allocator & alloc) :
        m_Ids(alloc),
        m_Labels(alloc),
        m_Values(alloc) {
    }
    ~Details() {}

    int Read(BinaryReader & br);

private:
    shm::int_vector m_Ids;
    shm::string_vector m_Labels;
    shm::string_vector_vector m_Values;
};

int Details::Read(BinaryReader & br) {
    int num = br.ReadInt();

    m_Ids.resize(num);
    m_Labels.resize(num);
    m_Values.resize(num);

    for (int i = 0; i < num; i++) {
        m_Ids[i] = br.ReadInt();
        m_Labels[i] = br.ReadString().c_str();

        int count = br.ReadInt();
        m_Value[i].resize(count);
        for (int j = 0; j < count; j++) {
            m_Value[i][j] = br.ReadString().c_str();
        }
    }
}

But when I compile it, I get the error:
'boost::interprocess::allocator<T,SegmentManager>::allocator' : no appropriate default constructor available

And it's due to the resize() calls on the vector objects. Because the allocator types do not have a empty constructor (they take a const segment_manager_t &) and it's trying to create a default object for each location. So in order for it to work, I have to get an allocator object and pass a default value object on resize. Like this:

int Details::Read(BinaryReader & br) {
    shm::void_allocator alloc(m_Ids.get_allocator());
    int num = br.ReadInt();

    m_Ids.resize(num);
    m_Labels.resize(num, shm::string(alloc));
    m_Values.resize(num, shm::string_vector(alloc));

    for (int i = 0; i < num; i++) {
        m_Ids[i] = br.ReadInt();
        m_Labels[i] = br.ReadString().c_str();

        int count = br.ReadInt();
        m_Value[i].resize(count, shm::string(alloc));
        for (int j = 0; j < count; j++) {
            m_Value[i][j] = br.ReadString().c_str();
        }
    }
}

Is this the best/correct way of doing it? Or am I missing something.

Thanks!

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

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

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文