是对输入迭代器这个正确的行为,关于访问的最后一个项目:得到最后一个项目
for(i=being();i!=end();i++){}
std::string s = i->toString();
return s;
还是应该抛出一个异常,如果我尝试这样做?
我的迭代器利用了两个C函数调用:getFirst(...)和GetNext(...)
是对输入迭代器这个正确的行为,关于访问的最后一个项目:得到最后一个项目
for(i=being();i!=end();i++){}
std::string s = i->toString();
return s;
还是应该抛出一个异常,如果我尝试这样做?
我的迭代器利用了两个C函数调用:getFirst(...)和GetNext(...)
不,这也不行,你会被提领end()
和调用未定义的行为。考虑:
int main()
{
int i = 0;
for (; i < 42; ++i) ;
std::cout << i; // prints 42, did you expect 41?
}
除非你在这种情况下实现了你的迭代器类来做一些明智的事情。然而,这对于标准库迭代器来说并不好。
这不是一个正确的行为。 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今天所有的upvoters在哪里? :P – jrok
就stl容器而言,这是不正确的行为。
端()
返回一个迭代参照过去最端部元件在列表 容器。
这意味着你的循环后,我不指向一个正确的对象(而不是最后一个元素),而是指向一个特殊的定义的最终值,这将导致访问冲突调用i->的toString()。
行为是未定义的,在实现迭代器时无需做任何事情(甚至不需要引发异常)。在实施InputIterators,你只需要执行的操作
iter == iter2
,iter != iter2
*iter
,iter->...
++iter
,(void)iter++
*r++
其中,只有最后一个是很难(当你将迭代器移到时,你必须返回前一个位置的数据下一个)。它通常由一个代理来实现,它记住了旧数据。
这应该工作,除了你拼写'开始'错误。 – Daniel
@RedX,Daniel:这是错误的,'i == end()'在循环结束后。 – kennytm
@血液我正在移动到最后,然后访问最后一个项目。由于迭代器只有函数的第一个和下一个我不能跳到最后一步 – Baz