无法递增值初始化 map/set 迭代器

Cannot increment value-initialized map/set iterator

我试图在映射中的索引 j 之后递增节点的键,但是在将迭代器递增到下一个节点时出现了一些错误,这是我的代码:

typedef map<int, string> My_map;    
My_map my_map;
my_map[0] = "la base";
my_map[1] = "le premier";

int j = 1;

My_map::reverse_iterator first_it(my_map.rbegin());
first_it++;
My_map::reverse_iterator last_it(make_reverse_iterator(next(my_map.begin(), j - 1)));

for (My_map::reverse_iterator it = first_it ; it != last_it ; it++) {
    auto handle = my_map.extract(it.base());
    handle.key()++;
    my_map.insert(move(handle));
}

我知道一个映射不能有重复的键,所以我开始从最后一个递增到第 j 个。但是 it++ 不起作用。和我用first_it++;的时候不一样吗?

std::map::extractdocumentation 中提到 side-effects:

Extracting a node invalidates only the iterators to the extracted element. Pointers and references to the extracted element remain valid, but cannot be used while element is owned by a node handle: they become usable if the element is inserted into a container.

如您所见,所有迭代器都已找到 except 您关心的迭代器。因为 it 是提取元素的迭代器,所以现在无效。随后尝试使用它(使用 it++ 来推进循环迭代)会导致未定义的行为。

你可以做的是使用 std::map::insert:

返回的迭代器
auto result = my_map.insert(move(handle));
it = make_reverse_iterator(result.position);

作为@paddy 的,在调用.extract() 方法并再次执行.insert() 之后,所有迭代器都无效,因此您不能运行 进一步修改循环.

我建议采用以下有效且更快的解决方案。到单独的 std::vector 复制从第 j 位置开始的所有元素。在地图中删除它们。以您喜欢的方式在向量中修改它们,例如通过将 +1 添加到所有键。通过地图的 .insert(begin, end) 方法一次将它们全部插入。清除复制元素的向量。

所有建议都在下面的代码片段中实现:

Try it online!

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

int main() {
    std::map<int, std::string> m;
    m[0] = "la base";
    m[1] = "le premier";

    int j = 1;

    auto const j_it = std::next(m.begin(), j);
    std::vector<std::pair<int, std::string>> vcopy(j_it, m.end());
    m.erase(j_it, m.end());
    for (auto & [k, v]: vcopy)
        ++k;
    m.insert(vcopy.begin(), vcopy.end());
    vcopy.clear();

    // Show map
    for (auto const & [k, v]: m)
        std::cout << k << ": " << v << std::endl;
}

输出:

0: la base
2: le premier