如何将迭代器增加2?

有人能告诉我如何将迭代器增加2吗?

iter++是可用的-我必须做 iter+2吗? 我怎样才能做到这一点?

129376 次浏览

You could use the 'assignment by addition' operator

iter += 2;

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.

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)

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.

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.

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

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

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);
}