acgtyrant
acgtyrant

Reputation: 1829

In the computation of iterators, if I use an iterator which is before begin() or after end() as a operand, is its behavior defined?

I tried an experiment:

#include <iostream>
#include <vector>

int main(void) {
  std::vector<int> a{1, 2, 3};
  std::vector<int>::iterator b = a.begin();
  std::vector<int>::iterator c = a.end();
  std::vector<int>::iterator d = b - 1;
  std::vector<int>::iterator e = c + 1;
  std::cout << true << std::endl;
  std::cout << (d < b) << std::endl;
  std::cout << (e > c) << std::endl;
  return 0;
}

It outputs:

1
1
1

But someone told me that it is behavior undefined for deque, so what do you think? Thank you!

Upvotes: 1

Views: 110

Answers (3)

Bathsheba
Bathsheba

Reputation: 234655

The behaviour on using either d or e is undefined, as you suspected.

You are allowed to test c for equality with a.end(), but note that the behaviour on any dereferencing it is undefined.

Upvotes: 0

Lightness Races in Orbit
Lightness Races in Orbit

Reputation: 385104

No.

Both d and e are "singular iterators" because they point neither to an element in a sequence, or to the "one-past-the-end" pseudo-element.

And you can barely do anything with singular iterators:

[C++11: 24.2.1/5]: Just as a regular pointer to an array guarantees that there is a pointer value pointing past the last element of the array, so for any iterator type there is an iterator value that points past the last element of a corresponding sequence. These values are called past-the-end values. Values of an iterator i for which the expression *i is defined are called dereferenceable. The library never assumes that past-the-end values are dereferenceable. Iterators can also have singular values that are not associated with any sequence. [ Example: After the declaration of an uninitialized pointer x (as with int* x;), x must always be assumed to have a singular value of a pointer. —end example ] Results of most expressions are undefined for singular values; the only exceptions are destroying an iterator that holds a singular value, the assignment of a non-singular value to an iterator that holds a singular value, and, for iterators that satisfy the DefaultConstructible requirements, using a value-initialized iterator as the source of a copy or move operation.

Note that, in particular, you cannot perform arbitrary comparisons on them.

I was pretty sure that even evaluating a.begin() - 1 or a.end() + 1 were UB, but I can't find any evidence of that right now.

Upvotes: 3

Mark B
Mark B

Reputation: 96243

Not just for deque but this is undefined for any container (only random access containers will actually allow this to compile though).

Upvotes: 2

Related Questions