在C++11的std::map中,是否存在一些有效的迭代器x,以保证++x等于map::begin()?我想检测我刚才调用的函数(我的函数)是否已经从函数的前面遍历了迭代器。该函数将迭代器向后移动一个位置。
这个答案适用于图书馆的其他部分吗?
发布于 2013-10-17 02:32:14
不,在std容器中开始之前的迭代器都是UB (除了反向迭代器,这可能解决不了您的问题)。
您可能需要修复有关的函数。如果做不到这一点,那就把它包起来,在你打电话之前抓住它的坏行为。否则,您可以在map键类型排序中插入一个负无穷大元素,并添加一个键值。否则,您可以编写迭代器适配器,将您的map迭代器封装为可以在不使用UB的情况下先执行一次的迭代器。
这些是按我推荐的顺序排列的,大致上是这样的。每一种方法都可能失败,而且随着我的推荐变得更加遥远,它们更容易出错,也更危险。
发布于 2013-10-17 08:26:10
非常重要的是要认识到标准库容器是半开放范围[begin, end),也就是说,您可以迭代一次过结束。对于双向(和随机)迭代器,您也可以执行--end()并从边缘返回。*end()删除一个过端是未定义的行为,--begin()或begin() - 1减少开始迭代器也是如此。只有一个例外:std::forward_list,它有一个满足++before_begin() == begin()的不可解除引用的迭代器before_begin() (但请注意,对于forward_list,您也不能减少begin() )。
这种双向迭代器的基本不对称性意味着反向迭代器是规则迭代器的薄包装器。在大多数标准库实现中,它们只是包含底层迭代器的副本base_。递增一个std::reverse_iterator调用类似于--base_; return *this;的东西,并取消引用它可以执行auto old = base_; return *--old;。底层迭代器绝不会减少到begin()之前,也不会以这种方式取消对end()的引用。
下面是支持双向或随机迭代器的容器上迭代的四种方法,以及各种迭代器之间的关系(.base()将std::reverse_iterator转换回其底层迭代器)
#include <iomanip>
#include <iostream>
#include <iterator>
#include <map>
#include <string>
int main()
{
auto c = std::map<int, std::string>{ {1, "hello"}, {2, "world"} };
{ // 1) forward iteratation
auto it = begin(c);
for (; it != end(c); ++it){}
std::cout << std::boolalpha << (it == c.rbegin().base()) << "\n";
}
{ // 2) meh, backward iteration
auto it = end(c) - 1; //end return iterator after the last element.
for (; it != begin(c); --it){}
std::cout << std::boolalpha << (it == c.rend().base()) << "\n";
}
{ // 2') better: reverse iteration
auto it = c.rbegin();
for (; it != c.rend(); ++it){}
std::cout << std::boolalpha << (it.base() == begin(c)) << "\n";
}
{ // 1') backward reverse, better avoid this
auto it = c.rend();
for (; it != c.rbegin(); --it){}
std::cout << std::boolalpha << (it.base() == end(c)) << "\n";
}
}Live Example
如果您的数据结构应该支持双向迭代,但没有成员迭代器.rbegin()或rend(),那么您可以轻松地通过std::reverse_iterator(end())和std::reverse_iterator(begin())分别定义它们(这也是标准库通常实现它们的方式)。
发布于 2013-10-17 02:22:52
通过“让迭代器离开前面”,我猜想您正在减少一个前迭代器,如下所示:
// don't do this:
for(it = mymap.end(); --it >= mymap.begin(); ) { ... }相反,增加如下反向迭代器:
// this is better:
for(it = mymap.rbegin(); it != mymap.rend(); ++it) { ... }-Jesse
https://stackoverflow.com/questions/19417171
复制相似问题