C++11 - 二维地图上基于范围的 for 循环

C++11 - Range-based for loop on a two-dimensional map

我有一张二维地图,我是这样声明的:

typedef std::map<std::string, std::map<std::string, Objective>> objectives_t;

我想将这张二维地图的内容保存到一个文件中。

所以我尝试了类似的东西,灵感来自我在网上找到的一些代码:

for (auto const &subject : m_objectives) {
    for (auto const &objective : m_objectives[subject.first]) {
        //Print the objective
    }
}

当然,这行不通。我应该怎么做?我不太确定 subject 和 objective 是什么(它们是迭代器吗?)。

在第二行,我得到:

error: passing 'const objectives_t {aka const std::map<std::basic_string<char>, std::map<std::basic_string<char>, Objective> >}' as 'this' argument of 'std::map<_Key, _Tp, _Compare, _Alloc>::mapped_type& std::map<_Key, _Tp, _Compare, _Alloc>::operator[](const key_type&) [with _Key = std::basic_string<char>; _Tp = std::map<std::basic_string<char>, Objective>; _Compare = std::less<std::basic_string<char> >; _Alloc = std::allocator<std::pair<const std::basic_string<char>, std::map<std::basic_string<char>, Obj|

你的外循环是正确的。但是内部应该遍历 subject.second

for (auto const &subject : m_objectives) {
    for (auto const &objective : subject.second) {
        // print out objective.second
    }
}

这是因为在第一个基于范围的 for 循环之后,subject 具有类型

std::pair<const std::string, std::map<std::string, Objective>> const&

所以每一项都是

subject.first    // std::string
subject.second   // std::map<std::string, Objective>

然后当您迭代 subject.second 时,您的 objective 现在是

std::pair<const std::string, Objective> const&

所以再次拆开元素

objective.first    // std::string
objective.second   // Objective

m_objectives就是上面代码中的const

operator[] 不适用于 const 映射,因为它被定义为在找不到密钥时修改映射。

这就是你的错误所在。请注意,如果它以某种方式修改了映射,则外循环将被搞砸,因此映射是 const 有点幸运。正如您所指出的,在这种情况下它实际上不会修改它(因为您正在从它自己反馈密钥)。

无论如何,[] 将是低效的,因为当您有值部分时,它会生成额外的地图查找。

修复很简单:

for (auto const &subject : m_objectives) {
  for (auto const &objective : subject.second) {
    //Print the objective
  }
}

既正确(因为它不在 const map 上使用 []),又更快(因为如果你取消 const-化 map m_objectives 不知何故,在遍历地图时使用 [] 既效率低下又容易出错。