[英]How to use emplace/insert_or_assign in nested map with c++17?
如果我有
map<int, map<int, int>> m;
当我需要插入时,我可以使用
m[1] = { {1, 1} };
但是现在我想用 emplace/insert_or_assign 来代替它,我可能会用
m.emplace(1, map<int, int>{ {1, 1} });
但是我觉得写起来有点复杂,特别是我应该重新写map<int, int>
,如果原来的map改成比如map<int, map<int, map<int, map<int, int>>>>
就更map<int, map<int, map<int, map<int, int>>>>
,那么我应该根据需要重复map<int, int>
。 那么有没有更简单易读的方法呢?
问题应该是为什么要在第一点使用emplace
/ insert_or_assign
。
emplace
点是为了让您在需要之前不要进行不必要的创建。 使用map<int, map<int, int>>
,您可能只想在要插入新的 map 时才创建内部 map。要正确利用这种行为,您应该只提供构建 map 的 arguments,不是 map 本身。
但是,唯一的构造函数map
也可以在构造过程中填充容器是采用initializer_list
的构造函数。 所以理想情况下你会想写这样的东西:
m.emplace(1, {{1, 1}}) // this won't work
但是,这是行不通的,因为emplace
无法将{{1, 1}}
推断为initializer_list
。 这意味着您必须手动指定,例如:
m.emplace(1, std::initializer_list<std::pair<const int, int>>{{1, 1}})
这是相当多的写作,如果你有更多的嵌套层,那只会更糟。 在这一点上,最好只写:
if (m.find(1) == m.end()) {
// or `!m.contains(1)` for C++20 or later
m[1] = {{1, 1}};
}
另一方面,如果你真的不关心不必要的构造,你应该只使用insert
代替:
m.insert({1, {{1, 1}}})
insert_or_assign
的要点是使 map 适用于不可默认构造的类型。
当您只调用m[1]
时,如果m[1]
不存在,这将默认构造一个 object。 但是,这也意味着如果类型不是默认可构造的,则operator[]
不起作用。
但是,由于map
是默认可构造的,因此直接使用operator[]
与使用insert_or_assign
之间没有太大区别。 因此,只有 go 使用operator[]
。
你可以做
typedef map<int, int> mp;
然后做
m.emplace(1, mp{ {1, 1} });
这不那么冗长,也清楚地表明什么是 map 构造函数,什么不是。
希望这可以帮助。
编辑:您也可以尝试做
template <typename T>
using nest_mp = std::map<int, T>;
typedef std::map<int, int> mp;
并做
m.emplace(1, nest_mp<nest_mp<mp>>>{ {1, { {1, { {1, 1} } } } } };
每个 map 构造都有两个{
大括号 - 一个调用std::map
初始化列表构造函数,另一个调用std::pair
初始化列表构造函数。
最好根本不要使用map<int, map<int, int>>
。 相反,使用map<std::pair<int, int>, int
。 这意味着你有一个组合键,所以不是将值存储在[A][B]
中,而是将它存储在[pair(A, B)]
中。 这样,当您存储一个值时,它总是为其节点分配一个 memory 分配(因为只有一个映射)。
然后你写这样的代码:
m.emplace(std::make_pair(1, 1), 1);
m.insert_or_assign({1, 1}, 1);
如果你想用键中的特定“第一个”integer 迭代值:
int subkey = 1;
for (auto it = m.lower_bound({subkey, 0}),
end = m.upper_bound({subkey, INT_MAX});
it != end; ++it)
{
// do something with elements whose key.first == subkey
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.