Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

std::advance behavior when advancing beyond end of container [duplicate]

Tags:

c++

stl

What is the behavior of std::advance when you have say:

std::vector<int> foo(10,10); auto i = foo.begin(); std::advance(i, 20); 

What is the value of i? Is it foo.end()?

like image 585
Raindog Avatar asked May 06 '11 19:05

Raindog


People also ask

What does std :: advance do?

std::advance advances the iterator 'it' by n element positions. Syntax : template void advance (InputIterator& it, Distance n); it : Iterator to be advanced n : Number of element positions to advance. This shall only be negative for random-access and bidirectional iterators.

Which operator is used to point to the next element in the container?

Operator (++) : The '++' operator increments the iterator by one. Therefore, an iterator points to the next element of the container. Operator (==) and Operator (!=) : Both these operators determine whether the two iterators point to the same position or not.

What does std :: next return?

std::next returns an iterator pointing to the element after being advanced by certain no. of positions. It is defined inside the header file . It does not modify its arguments and returns a copy of the argument advanced by the specified amount.


2 Answers

The standard defines std::advance() in terms of the types of iterator it's being used on (24.3.4 "Iterator operations"):

These function templates use + and - for random access iterators (and are, therefore, constant time for them); for input, forward and bidirectional iterators they use ++ to provide linear time implementations.

The requirements for these operations on various iterator types are also outlined in the standard (in Tables 72, 74, 75 and 76):

  • For an input or forward iterator

    ++r precondition: r is dereferenceable 
  • for a bidirectional iterator:

    --r precondition: there exists s such that r == ++s 
  • For random access iterators, the +, +=, -, and -= operations are defined in terms of the bidirectional & forward iterator prefix ++ and -- operations, so the same preconditions hold.

So advancing an iterator beyond the 'past-the-end' value (as might be returned by the end() function on containers) or advancing before the first dereferenceable element of an iterator's valid range (as might be returned by begin() on a container) is undefined behavior since you're violating the preconditions of the ++ or -- operation.

Since it's undefined behavior you can't 'expect' anything in particular. But you'll likely crash at some point (hopefully sooner rather than later, so you can fix the bug).

like image 188
Michael Burr Avatar answered Sep 26 '22 19:09

Michael Burr


According to the C++ Standard §24.3.4 std::advance(i, 20) has the same effect as for ( int n=0; n < 20; ++n ) ++i; for positive n. From the other side (§24.1.3) if i is past-the-end, then ++i operation is undefined. So the result of std::advance(i, 20) is undefined.

like image 42
Kirill V. Lyadvinsky Avatar answered Sep 24 '22 19:09

Kirill V. Lyadvinsky