结束迭代器递减的可移植性如何?
刚刚在我的公司源代码中遇到了 end()
迭代器的递减,这对我来说看起来很奇怪。据我记得这在某些平台上有效,但在其他平台上无效。也许我错了,但是我在标准中找不到任何有用的东西。标准只说 end()
返回一个迭代器,它是最后的值,但它保证是可递减的吗?这样的代码如何符合标准?
std::list<int>::iterator it = --l.end();
提前致谢。
Just encountered decrement of end()
iterator in my company source codes and it looks strange for me. As far as I remember this was working on some platforms, but not for the others. Maybe I'm wrong, however I couldn't find anything useful in standard about that. Standard only says that end()
returns an iterator which is the past-the-end value, but is it guaranteed to be decrementable? How does code like that match the standard?
std::list<int>::iterator it = --l.end();
Thanks in advance.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
我认为这是相关条款:
因此,对于列出的容器,不仅从
end()
返回的迭代器应该是可递减的,递减后的迭代器也应该是可取消引用的。 (当然,除非容器是空的。这会调用未定义的行为。)事实上,
vector
、list
和deque
实现随Visual C++ 编译器的执行方式与表中的完全一样。当然,这并不意味着每个编译器都会这样做:请注意表中的代码:
因此,虽然实现确实可能无法根据
begin()
和end()
实现这些表达式,但 C++ 标准指定这两个表达式是等效的。换句话说,根据上述子句,a.back()
和*--a.end()
是等效的构造。在我看来,这意味着您应该能够将a.back()
的每个实例替换为*--a.end()
,反之亦然让代码仍然有效。根据 Bo Persson 的说法,我手头的 C++ 标准修订版 对于表 68 有缺陷。
看来您仍然可以递减从
end()
返回的迭代器并取消引用递减的迭代器,只要它不是临时的。I think this is the relevant clause:
So for the containers listed, not only should the iterator returned from
end()
be decrementable, the decremented iterator should also be dereferencable. (Unless the container is empty, of course. That invokes undefined behavior.)In fact,
vector
,list
anddeque
implementations that came with the Visual C++ compiler does it exactly like the table. Of course, that's not to imply that every compiler does it like this:Note about the code in the table:
So while it's true that an implementation may not implement those expressions in terms of
begin()
andend()
, the C++ standard specifies that the two expressions are equivalent. In other words,a.back()
and*--a.end()
are equivalent constructs according to the above clause. It seems to me that it means that you should be able to replace every instance ofa.back()
with*--a.end()
and vice-versa and have the code still work.According to Bo Persson, the revision of the C++ standard that I have on hand has a defect with respect to Table 68.
It appears that you can still decrement the iterator returned from
end()
and dereference the decremented iterator, as long as it's not a temporary.来自
std::prev
的文档这意味着前缀递减操作的实现可能不是内部类形式< code>iterator iterator::operator--(int) 但在类外部重载,形成
iterator operator--(iterator&, int)
。所以你应该选择
std::prev
或执行以下操作:<代码>
{ 自动结束 = a.end(); - 结尾; };
from the documentation for
std::prev
which means the implementation for the prefix decrement operation may not be the inside class form
iterator iterator::operator--(int)
but overloaded outside class formiterator operator--(iterator&, int)
.so you should either prefer
std::prev
or do the following:{ auto end = a.end(); --end; };
这段代码不行,如果列表为空,你就有麻烦了。
因此,检查一下,如果列表不为空,则代码非常好。
This code is not OK, in case list is empty you are in trouble.
So check for that, if list is not empty the code is very fine.