89

Can anybody tell me how to increment the iterator by 2?

iter++ is available - do I have to do iter+2? How can I achieve this?

ForceBru
  • 43,482
  • 10
  • 63
  • 98
Cute
  • 13,643
  • 36
  • 96
  • 112

8 Answers8

119

std::advance( iter, 2 );

This method will work for iterators that are not random-access iterators but it can still be specialized by the implementation to be no less efficient than iter += 2 when used with random-access iterators.

CB Bailey
  • 755,051
  • 104
  • 632
  • 656
  • 1
    What will happen if the iterator currently points onto the last element? Where will it point after the increment? I tried with VC++ - it just advances and comparison against vector::end() returns false after that. This is straight way to undefined behaviour, I suppose. – sharptooth Jun 29 '09 at 10:38
  • 1
    Yes, if you're going to do std::advance with '2', or +=2, or two '++' without checking for 'end' in the middle, then you need some external guarantee that you're not going to go beyond one past the end. (E.g. you might *know* that you're iterating through the even numbered (zero based) items of a collection which is guaranteed to have an even number of items.) – CB Bailey Jun 29 '09 at 11:24
  • what is difference between next( iter, 2) and next( iter, 2 ) – Mohammad Abdollahzadeh Jul 25 '17 at 06:36
35

http://www.cplusplus.com/reference/std/iterator/advance/

std::advance(it,n);

where n is 2 in your case.

The beauty of this function is, that If "it" is an random access iterator, the fast

it += n

operation is used (i.e. vector<,,>::iterator). Otherwise its rendered to

for(int i = 0; i < n; i++)
    ++it;

(i.e. list<..>::iterator)

Maik Beckmann
  • 5,637
  • 1
  • 23
  • 18
35

If you don't have a modifiable lvalue of an iterator, or it is desired to get a copy of a given iterator (leaving the original one unchanged), then C++11 comes with new helper functions - std::next / std::prev:

std::next(iter, 2);          // returns a copy of iter incremented by 2
std::next(std::begin(v), 2); // returns a copy of begin(v) incremented by 2
std::prev(iter, 2);          // returns a copy of iter decremented by 2
Piotr Skotnicki
  • 46,953
  • 7
  • 118
  • 160
  • If i have a an iterator like this: `map::iterator iter; for(iter = variations.begin(); iter != variations.end(); iter++) { map::iterator it_tmp = std::next(iter, 1); // increment by 1 it_tmp = std::next(iter, 2); // increment by 2 }` Will **iter** be incremented by 2 ? or *iter* will just affect it_tmp? – Hani Goc Feb 02 '16 at 11:13
  • @HaniGoc Only it_tmp – metamorphosis Nov 11 '16 at 20:52
9

You could use the 'assignment by addition' operator

iter += 2;
teabot
  • 15,358
  • 11
  • 64
  • 79
  • I was wondering if ++iter++ would work, but I think that would just be confusing. – Xetius Jun 29 '09 at 10:10
  • 2
    What will happen if the iterator currently points onto the last element? Where will it point after the increment? – sharptooth Jun 29 '09 at 10:11
  • 4
    @Xetius: You should not do it. It is undefined behavior. – Naveen Jun 29 '09 at 10:12
  • 2
    ++iter++ binds as ++(iter++), iter++ is not a modifiable lvalue so you can't 'do' ++(iter++). If it was allowed, it probably wouldn't do what might be expected of it. – CB Bailey Jun 29 '09 at 10:14
  • 3
    This doesn't work for all iterator types. Only RandomAccessIterators are required to support addition. – Steve Jessop Nov 05 '10 at 23:04
9

We can use both std::advance as well as std::next, but there's a difference between the two.

advance modifies its argument and returns nothing. So it can be used as:

vector<int> v;
v.push_back(1);
v.push_back(2);
auto itr = v.begin();
advance(itr, 1);          //modifies the itr
cout << *itr<<endl        //prints 2

next returns a modified copy of the iterator:

vector<int> v;
v.push_back(1);
v.push_back(2);
cout << *next(v.begin(), 1) << endl;    //prints 2
skpro19
  • 519
  • 7
  • 10
6

If you don't know wether you have enough next elements in your container or not, you need to check against the end of your container between each increment. Neither ++ nor std::advance will do it for you.

if( ++iter == collection.end())
  ... // stop

if( ++iter == collection.end())
  ... // stop

You may even roll your own bound-secure advance function.

If you are sure that you will not go past the end, then std::advance( iter, 2 ) is the best solution.

Jem
  • 2,255
  • 18
  • 25
0

Assuming list size may not be an even multiple of step you must guard against overflow:

static constexpr auto step = 2;

// Guard against invalid initial iterator.
if (!list.empty())
{
    for (auto it = list.begin(); /*nothing here*/; std::advance(it, step))
    {
        // do stuff...

        // Guard against advance past end of iterator.
        if (std::distance(it, list.end()) > step)
            break;
    }
}

Depending on the collection implementation, the distance computation may be very slow. Below is optimal and more readable. The closure could be changed to a utility template with the list end value passed by const reference:

const auto advance = [&](list_type::iterator& it, size_t step)
{
    for (size_t i = 0; it != list.end() && i < step; std::next(it), ++i);
};

static constexpr auto step = 2;

for (auto it = list.begin(); it != list.end(); advance(it, step))
{
    // do stuff...
}

If there is no looping:

static constexpr auto step = 2;
auto it = list.begin();

if (step <= list.size())
{
    std::advance(it, step);
}
evoskuil
  • 1,011
  • 1
  • 7
  • 13
-9

The very simple answer:

++++iter

The long answer:

You really should get used to writing ++iter instead of iter++. The latter must return (a copy of) the old value, which is different from the new value; this takes time and space.

Note that prefix increment (++iter) takes an lvalue and returns an lvalue, whereas postfix increment (iter++) takes an lvalue and returns an rvalue.

Jonas Kölker
  • 7,680
  • 3
  • 44
  • 51