从输入迭代器中获取最后一项

时间:2012-07-02 14:02:03

标签: c++

对于输入迭代器,这是正确的行为,关于访问最后一项:

for(i=being();i!=end();i++){}
std::string s = i->toString();
return s;

或者如果我尝试这样做会引发异常吗?

我的迭代器使用两个c函数调用:getFirst(...)和getNext(...)

4 个答案:

答案 0 :(得分:2)

这不是正确的行为。 C ++中的标准约定是,end()应指向最后一项之外的位置。取消引用它通常会导致未定义的行为(C ++11§24.2.2/ 5)。

您可以让自己的迭代器原谅解除引用end()并利用它,但它会偏离标准做法,并使人们难以理解您的代码。我建议你抛出异常,而不是返回最后一项。


在标准C ++中,如果您拥有的是一个不可重现的输入迭代器,除非您每次都提取它,否则无法“获取最后一项”:

auto it = begin();
auto val;
while (it != end()) {
    val = *it;
    ++ it;
}
return val;

但是如果你可以创建一个前进迭代器,那么你可以使用

auto iter = begin();
decltype(iter) last_iter;
while (true) {
    last_iter = iter++;
    if (iter == end())
        break;
}
return last_iter;

或者如果你创建输入迭代器两次便宜,你可以进行两次迭代:

auto dist = std::distance(begin(), end());
auto last_iter = begin();
std::advance(last_iter, dist - 1);
return last_iter;

答案 1 :(得分:0)

不,这不行,您将取消引用end()并调用未定义的行为。考虑:

int main()
{
    int i = 0;
    for (; i < 42; ++i) ;
    std::cout << i;    // prints 42, did you expect 41?
}

当然,除非你在这种情况下实现了迭代器类来做一些合理的事情。但是,这对于标准库迭代器来说并不合适。

答案 2 :(得分:0)

就stl容器而言,这是不正确的行为。

端()

  

返回一个迭代器,引用列表中的past-the-end元素   容器

这意味着在循环之后,我没有指向正确的对象(不是最后一个元素),而是指向特殊定义的结束值,这会导致调用i-&gt; toString时出现访问冲突( )。

答案 3 :(得分:0)

行为是未定义的,在实现迭代器时不需要做任何事情(甚至不需要抛出异常)。实现InputIterators时,您只需实现操作

  • iter == iter2iter != iter2
  • *iteriter->...
  • ++iter(void)iter++
  • *r++

其中,只有最后一个很难(你必须从前一个位置返回数据,而迭代器移动到下一个位置)。它通常由代理实现,它会记住旧数据。