C++ 这是正确的行为吗?映射迭代器无效

C++ 这是正确的行为吗?映射迭代器无效,c++,iterator,stdmap,C++,Iterator,Stdmap,根据标准,这真的是应该发生的吗?我没有触及反向,但它所指向的值正在变化。我认为std::map中的迭代器应该是安全的,不会被插入。然而,它似乎在决定,逆向工程不是停留在我告诉它的价值上,而是“在这个时间点上,地图末尾发生的任何事情” 更新:进一步的信息,以防影响:这似乎不会发生在前向迭代器上(在任何情况下,我都能找到),我的gcc版本是5.1.1-4。如这里所引用 反向迭代器将迭代器存储到下一个元素,而不是它实际引用的元素 副作用是,如果在该迭代器(包括end())之前插入某些内容,则在取消引用

根据标准,这真的是应该发生的吗?我没有触及反向,但它所指向的值正在变化。我认为std::map中的迭代器应该是安全的,不会被插入。然而,它似乎在决定,逆向工程不是停留在我告诉它的价值上,而是“在这个时间点上,地图末尾发生的任何事情”

更新:进一步的信息,以防影响:这似乎不会发生在前向迭代器上(在任何情况下,我都能找到),我的gcc版本是5.1.1-4。

如这里所引用

反向迭代器将迭代器存储到下一个元素,而不是它实际引用的元素


副作用是,如果在该迭代器(包括end())之前插入某些内容,则在取消引用该反向迭代器时将看到该新值。我不认为反向迭代器在这种情况下失效。根据C++标准(23.2.4个关联容器)

< < /P> < P> 9插入件和安放件不得影响插入件和安放件的有效性 迭代器和容器引用,以及擦除成员 仅使迭代器和对已删除元素的引用无效

另一方面(24.5.1反向迭代器)

1类模板反向迭代器是迭代的迭代器适配器 从其基础迭代器定义的序列的结尾到 这一序列的开始

虽然在最后一段引文中提到了类
std::reverse_iterator
,但这同样适用于标准容器的反向迭代器

根据表97-可逆容器要求

rbegin()
对应于
反向迭代器(end())

因此,在您的示例中,反向迭代器仍然对应于
end()
。 `
map.rbegin()
返回一个迭代器,该迭代器等于
std::reverse_迭代器(map.end())

当您取消引用反向迭代器时,问题就会出现。当您取消引用
反向迭代器时,实际获得的值来自迭代器,然后该值存储在
反向迭代器中。这可能看起来很奇怪,但有很好的理由,这是不可避免的。这样,为了安排范围的结束元素的过去:当反转时,指向范围中结束元素过去的迭代器指向范围的最后一个元素(而不是过去的元素)(这将是反转范围的第一个元素)。如果范围中第一个元素的迭代器被反转,则反转的迭代器将指向第一个元素之前的元素(这将是经过反转范围的结束元素)

也就是说,在您的情况下,当取消对
反向的引用时
等同于执行以下操作:

1, 1
2, 2

因此,在第二个
放置后
地图的最后一个元素发生了变化,并且取消了对
(-map.end())
(即,您的
反向放置
)的引用,您得到了地图中新的最后一个元素。

被“作废”和指向新数据不是一回事,是吗?它是指向容器中最后一对的有效指针。这一对恰好发生了变化,而前向迭代器不会发生这种情况。将rbegin替换为begin,将(2,2)替换为(0,0)。再说一次,这符合标准吗?因为这真是出乎意料,这是肯定的。对了,你放在地图上的第一件事不会改变。然而,你做的最后一件事是:地图中没有任何东西在改变——迭代器指向的东西在改变,而我不去碰迭代器。为什么?这符合标准吗?迭代器被设计成一个指针——你把它指向某个东西,它一直指向那里,一直有效,直到你把它指向另一个东西或者它失效。事实上,前向迭代器似乎就是这样。但不是相反。这有什么意义?在任何类型的非常量上下文中使用反向迭代器都是一个巨大的问题;常规的
迭代器
您的
反向迭代器
包含的是
end()
迭代器,即使在
放置
之后,该迭代器仍然有效。当您取消引用
reverse\u迭代器
时,它会减少
end()
迭代器并取消对结果的引用,这将提供您看到的输出。因此,基本上,它被设计打破了:Þ更改您正在使用的迭代器旁边的内容可以更改您正在使用的迭代器吗?太好了…:但是,如果这是标准所说的,我无能为力。我认为你混淆了“有效”和“一致”。Invalid是一个非常特殊的东西,它意味着不应该使用迭代器,因为它将导致未定义的行为。您对迭代器指向的内容在操作映射后不会发生更改的期望没有得到满足,但这不是标准的问题。考虑到迭代器的全部目的是替代指针和索引,我想说,当你修改他们没有指向的东西时,让他们改变的标准是非常不符合的。我还想说,在正向迭代器和反向迭代器之间存在行为不一致也是非常不好的。但事实就是这样。
*(--map.end());
*(--map.end());
std::map<int, int> map2;
map2.emplace(2, 2);
auto fiter = map2.begin();
std::cout << fiter->first << ", " << fiter->second << std::endl;
map2.emplace(1, 1);
std::cout << fiter->first << ", " << fiter->second << std::endl;
fiter = map2.begin();
std::cout << fiter->first << ", " << fiter->second << std::endl;
2, 2
2, 2
1, 1