std::list<>:l.begin()之前的元素

4

简短的问题:使用其他编译器(而非mingw32)是否会使以下代码不安全,或者可以继续使用?

list<int> l;
/* add elements */
list<int>::iterator i = l.begin();
i--;
i++;
cout << *i << endl;

换句话说,这意味着在执行此操作后,i是否被定义为指向l.begin()

2个回答

12

是的,这段代码是不安全的。如果在begin()之前尝试移动,你将导致未定义行为。尝试"再次后退"可能无法正常工作。


只要你的列表不为空,那就没问题。你会在列表中的最后一个“真实”元素处。++list.end() 将是未定义的。 - Vanessa MacDougal
2
@SethCarnegie:list.end()不是一个左值,因此它不是良好的形式。仅当列表不为空时,您才可以将指向list.end()的迭代器递减。 - CB Bailey
1
请注意,支持此(正确)答案的标准文献为C++03的§24.1.4/1和C++0x FDIS的§24.2.6/1。 - ildjarn
1
@ildjarn:哇!你怎么得到了C++11的副本?太神奇了!特别是它还没有被出版... - Lightness Races in Orbit
2
@Tomalak:他可以拥有一个引用,但是如果他取消引用它,他将引用未定义的标准。 - Kerrek SB
显示剩余5条评论

2
一个std::list通过链表指针遍历其内容,因此不使用指针算术来计算正确的位置。从.begin()开始的前一个位置将没有数据,并且不应提供任何有效的遍历机制。
像std::vector这样的容器具有随机访问迭代器,并且在底层使用指针算术,因此它们可能会给出正确的结果(没有问题),但这仍然是一个坏主意。
所以,它不应该工作,是未定义的,即使它以某种方式工作,也不要这样做 :)

链表和指针是完整的实现细节。 - Lightness Races in Orbit
std::vector<> 这样的容器的迭代器仍然受到标准中关于双向迭代器的规则的约束,该规则明确指出这是未定义的行为。 - ildjarn
是的,我同意两个评论 - 它是未定义的,并且链表是一种实现细节。但在他的情况下,它可能不起作用,因为它几乎肯定是一个链表,并且双向迭代器最可能使用指针算术运算符来处理向量,因此应该允许超出边界的移动。虽然这些假设是违反标准并且不好的,但我认为他们对他考虑会很有帮助。如果我增加了一些混淆,那么请原谅!:( - John Humphreys

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接