c++ 用boost multi-index代替mapped vector是否合理?

cdmah0mi  于 12个月前  发布在  其他
关注(0)|答案(1)|浏览(236)

在我的应用程序中,我存储了一个巨大的(!)容器:一个vector的vector。每个vector都有一个唯一的名称,我使用一个map来存储vector的索引以供进一步访问。在我的应用程序中,需要将数据存储在vector中,因为我必须进行大量的处理,因此需要快速访问其中的元素。
不幸的是,std::map不关心插入顺序,这在我的用例中很重要,我遇到了这个主题:
A std::map that keep track of the order of insertion?
不幸的是,所提出的解决方案并不完全是我所需要的,我现在想知道:

  • 可以让boost_multi_index使用vector来存储数据吗?
  • 用boost multi_index或者
  • 使用类似bimap或
  • 有没有更优雅的方式来表达“我的问题”?

示例代码:

#include <vector>
#include <map>
#include <string>
#include <iostream>

using payload_t = std::vector<uint32_t>;
using container_t = std::vector<payload_t>;
using container_map_t = std::map<std::string, size_t>;
using connectionMask_t = std::map<std::string, uint32_t>;

int main()
{
    container_t container;
    container_map_t container_map;

    // Store 1st payload
    container.push_back(std::move(payload_t{1,2,3}));
    container_map["One"] = container.size() - 1;

    // Store 2nd payload
    container.push_back(std::move(payload_t{4,5,6,7}));
    container_map["Two"] = container.size() - 1;

    // Store 3rd payload
    container.push_back(std::move(payload_t{8,9}));
    container_map["Three"] = container.size() - 1;

    // Assign unique mask to each layer (name)
    connectionMask_t masks;
    for (auto const&[name, data] : container_map)
    {
        // Assign mask to each layer
        masks[name] = 1UL << masks.size();
    }

    // Iterating vector access
    for (auto& outer : container)
        for (auto& inner : outer)
            std::cout << inner;
    std::cout << std::endl << std::endl;

    // Direct vector access
    for (auto& inner : container[1])
        std::cout << inner;
    std::cout << std::endl << std::endl;

    // Access via name
    for (auto& inner : container.at(container_map.at("Two")))
        std::cout << inner;
    std::cout << std::endl << std::endl;

    // Iterating access via map; order not preserved
    for (auto& [key, vec] : container_map)
    {
        std::cout << key << ": ";
        for (auto& inner : container[vec])
            std::cout << inner;
        std::cout << std::endl;
    }

    return 0;
}

字符串

z6psavjg

z6psavjg1#

  • 可以让boost_multi_index使用vector来存储数据吗?

所有容器都是在基于节点的存储上实现的,因此迭代器/引用的稳定性得到了保证。

  • 用boost multi_index [or]替换vector/map用法是否合理(在我的情况下)

看起来是这样,但看下面。

  • 使用类似bimap的东西

我不清楚它将如何填补任何空白。

  • 有没有更优雅的方式来表达“我的问题”?

也许。最简单的胜利,海事组织:

Live On Coliru

#include <cassert>
#include <cstdint>
#include <map>
#include <vector>

#include <fmt/ranges.h>

using payload_t = std::vector<uint32_t>;
using map_t     = std::map<std::string, payload_t>;
using entry_t   = map_t::value_type;
using ref_t     = std::reference_wrapper<entry_t>;

int main() {
    map_t              container;
    std::vector<ref_t> index;

    auto insert = [&](std::string name, payload_t element) {
        auto [it, ok] = container.emplace(std::move(name), std::move(element));
        if (ok)
            index.push_back(*it);
        else
            assert(false); // TODO decide on how to behave
    };

    for (auto&& [name, data] : { std::tuple //
             {"One", payload_t{1, 2, 3}},
             {"Two", payload_t{4, 5, 6, 7}},
             {"Three", payload_t{8, 9}},
         })
    {
        insert(std::move(name), data);
    }

    fmt::print("All (order not preserved): {}\n", container);

    for (int i = 0; entry_t& inner : index)
        fmt::print("At #{}, {}: {}\n", i++, inner.first, inner.second);

    fmt::print("Access via name: {}\n", container.at("Two"));
}

字符串
印刷

All (order not preserved): {"One": [1, 2, 3], "Three": [8, 9], "Two": [4, 5, 6, 7]}
At #0, One: [1, 2, 3]
At #1, Two: [4, 5, 6, 7]
At #2, Three: [8, 9]
Access via name: [4, 5, 6, 7]

从这里

加入你需要品尝的东西:

  • 升压容器
  • 稳定向量(稳定性)
  • 平面Map(用于参考位置和减少分配)
  • small_vector(例如,用于有效负载。在示例中,它们非常小,small_vector甚至static_vector将是一个巨大的性能提升)
  • Boost进程间

将所有这些放在共享内存/内存Map文件中。这将允许您处理比可用RAM大得多的数据结构,并在运行期间持久化

相关问题