在我的应用程序中,我存储一个巨大的(!)容器:向量的向量。 每个向量都有一个唯一的名称,我使用映射来存储索引 到向量以进行进一步访问。需要将数据存储在向量中 在我的应用程序中,因为我必须进行大量处理,因此需要 快速访问其中的元素。
不幸的是 std::map 不关心插入顺序 在我的用例中很重要,我遇到了这个主题:
不幸的是,所提出的解决方案并不完全是我所需要的,我现在想知道:
示例代码:
#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>;
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;
// 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;
}
- 是否可以让boost_multi_index使用向量来存储数据?
不。所有容器都在基于节点的存储上实现,因此保证了迭代器/引用的稳定性。
- 用 boost multi_index 替换矢量/地图使用是否合理(就我而言)[或]
似乎是这样,但请看下文。
- 使用bimap之类的东西
我不清楚它将如何填补任何空白。
- “我的问题”有更优雅的方式吗?
也许吧。最简单的胜利,IMO:
#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>;
template <> struct fmt::formatter<ref_t> {
auto format(ref_t r, auto& ctx) const { return format_to(ctx.out(), "{}", r.get().first); }
};
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]