C++11 中的过去终结迭代器失效
Past-the-end iterator invalidation in C++11
C++迭代器失效规则上最受欢迎的帖子声称,目前尚不清楚过去结束的迭代器(即由end()
、cend()
、rend()
和crend()
返回的迭代器)是否根据与普通迭代器相同的规则失效,这些规则指向容器中的元素。这些针对 2003 年和 2011 年C++提出的声明都遵循了讨论 End 迭代器无效规则的帖子,其中接受的答案表明 2003 年标准在这个问题上模棱两可。这个结论是基于 23.1/10 中的评论(在 swap()
的上下文中),该评论似乎暗示当规范没有明确提到过去结束迭代器的无效时,它们可能会失效。
对这篇文章问题的评论(由迈克-西摩提出)表明,就deque
而言,C++11在这件事上是明确的。我的问题是关于所有容器的:
- 在 C++11 中,是否有任何容器操作可能会使过去结束迭代器无效,以及此行为在语言规范中不明确?
换一种说法,
- 在执行容器操作后,我是否可以信任过去结束迭代器的有效性,该容器操作并未说明它可能使过去结束迭代器无效?
我的问题是关于所有容器的:
- 在 C++11 中,是否有任何容器操作可能会使过去结束迭代器无效,以及此行为在 语言规范?
我不确定你所说的"这种行为在语言规范中不明确"是什么意思,但肯定有一些操作会使过去的运算符无效(例如插入到std::vector
或std::string
中)。
换一种说法,
- 在执行未说明可能无效的容器操作后,我是否可以信任过去结束迭代器的有效性 过去的迭代器?
您可以像信任任何其他迭代器一样信任过去结束迭代器:任何不会(可能)使迭代器无效的操作都不会使它们失效。除了标准存在错误的可能性之外,这是所有没有说它们(可能)使操作员无效的操作。
如果标准说该操作不会使迭代器无效,您应该能够信任它。其他任何内容都应被视为标准库实现中的错误。
关于结束迭代器的失效规则,在 cppreference.com#Iterator_invalidation 中有一个提及。
相关行是:
过去的迭代器值得特别一提。通常,此迭代器是无效的,就好像它是未擦除元素的普通迭代器一样。因此,std::set::end 永远不会失效,std::unordered_set::end 仅在重新哈希时失效,std::vector::end 总是无效(因为它总是在修改的元素之后),依此类推。
有一个例外:删除 std::d eque 最后一个元素的擦除确实会使过去结束迭代器无效,即使它不是容器的擦除元素(或根本不是元素)。结合 std::d eque 迭代器的一般规则,最终结果是,唯一不会使 std::d eque::end 无效的修改操作是删除第一个元素,而不是最后一个元素。
另请参阅使用 std::set 的 end() - https://godbolt.org/z/5ecdqYod3 进行测试。
至少在GCC中,迭代器因std::map而失效:
#include <set>
#include <stdlib.h>
#include <assert.h>
int main() {
std::set<int> a;
a.insert(1);
std::set<int>::reverse_iterator rit(a.rbegin());
++rit;
assert(rit==a.rend());
a.erase(a.begin());
assert(a.rend()==rit); // FAIL
}
- std::vector::erase() 真的会在擦除时使迭代器失效吗?
- 没有迭代器失效是否意味着推进迭代器的有效性?
- C++11 std::列出拼接后的迭代器失效
- C++ std::map 和 std::set 擦除复制值,从而使迭代器失效
- 当没有迭代器失效时,这是否包括结束迭代器?
- std::map 线程安全和迭代器失效
- 赋值(运算符 =)使容器的迭代器失效
- std::list<>::splice 使迭代器失效。理由?
- C++11 中的过去终结迭代器失效
- 在字符串中使用 erase 函数是否会使迭代器失效
- tbb::concurrent_unordered_map::unsafe_erase 是否会使任何现有迭代器失效
- 迭代器失效 - end() 是否算作迭代器
- C++ deque:当迭代器失效时
- Unordered_map迭代器失效
- C++函数从列表中查找最小值.此函数是否正确,因为返回的迭代器失效
- 这是正确的行为吗?std::map 迭代器失效
- c++ multimap迭代器失效
- 如果STL容器中的迭代器失效,指针是否也会失效?
- 迭代器失效规则意味着线程安全吗?
- 为什么Vector中的Erase和Insert函数使迭代器失效?