无法递增值初始化 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::extract
的 documentation 中提到 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)
方法一次将它们全部插入。清除复制元素的向量。
所有建议都在下面的代码片段中实现:
#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
我试图在映射中的索引 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::extract
的 documentation 中提到 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)
方法一次将它们全部插入。清除复制元素的向量。
所有建议都在下面的代码片段中实现:
#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