繁体   English   中英

如何在嵌套的 map 和 c++17 中使用 emplace/insert_or_assign?

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM