访问最后一项,输入迭代器的行为是否正确:
for(i=being();i!=end();i++){}
std::string s = i->toString();
return s;
或者如果我尝试这样做,它应该抛出异常吗?
我的迭代器使用两个 c 函数调用:getFirst(...) 和 getNext(...)
这不是正确的行为。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;
不,这是不行的,您将取消引用end()
并调用未定义的行为。考虑:
int main()
{
int i = 0;
for (; i < 42; ++i) ;
std::cout << i; // prints 42, did you expect 41?
}
当然,除非你实现了迭代器类来在这种情况下做一些明智的事情。但是,这对于标准库迭代器来说是不行的。
就 stl 容器而言,这不是正确的行为。
结束()
返回引用列表中 past-theend 元素的迭代器 容器。
这意味着在您的循环之后,我不指向正确的对象(不是最后一个元素),而是指向一个特殊定义的结束值,这将导致调用 i->toString() 时出现访问冲突。
该行为是未定义的,在实现迭代器时无需对其进行任何操作(甚至不需要抛出异常)。实现输入迭代器时,只需实现操作
-
iter == iter2
,iter != iter2
-
*iter
,iter->...
-
++iter
,(void)iter++
-
*r++
其中,只有最后一个是困难的(你必须从上一个位置返回数据,而迭代器被移动到下一个位置)。它通常由代理实现,该代理会记住旧数据。