Should I use a range for a loop instead of iterators on a vector?

For the vc, vector vc, you can iterate over a vector with a range for:

 for (auto c : vc) std::cout << c; 

Or with an iterator:

 for (auto it = vc.cbegin(); it != vc.cend(); ++it) std::cout << *it; 

Is there a functional reason to use one method over another, or is it just a matter of style?

+6
source share
4 answers

In terms of performance, there really is no difference. As Bjarne Stroustrup writes in his book, the C ++ programming language 4th edition:

The simplest loop is the range for -statement; it just gives the programmer access to each element of the range.

As a fan of the KISS principle, I prefer simpler constructions over more complex ones. However, it really comes down to what you want to achieve. From the same book, Bjarne reveals why the range loop for a path is simple:

Note that the range-for loop is an intentionally simple construct. For example, using it, you cannot touch two elements at the same time and cannot effectively pass two ranges at the same time. For this we need a common operator.

Therefore, there are contexts in which you cannot use the range-for loop, and you must be in the classic for-statement.

The bottom line is used to loop the cycle whenever possible because it is simpler and easier to read.

+4
source

It is more or less a matter of style, but consider it that way; Loop ranges are shorter than using an explicit iterator. The less code you write, the less places where things can go wrong.

+4
source

In your specific example, they are equivalent. And since they are equivalent, you naturally want to prefer the shortest version, which will also be the least error prone - for free.

In addition, it is proposed to reduce the range, as well as:

 for ( var : range ) 

where var will be of type auto&& (aka forwading / universal reference), which is the best way to refer to an object. Just auto var will make a copy of each element, which may not be cheap. Unfortunately, he did not pass.

As a rule, you do not work with iterators directly, so you should be your first choice. Explicit iterators can also point to elements out of range, since you can move freely in a range, which leads to undefined behavior.

+2
source

There are two significant differences between the two examples. First, auto c creates a copy of each element, so use auto const& c if you do not want to create unnecessary copies. Secondly, the for range is implemented in terms of non-constant iterators, but constant iterators are used in the for loop. It doesn’t matter if vc is a standard container, but some containers (for example, those in Qt) implement copy-on-write semantics using an internal common pointer, in which case using non-constant iterators will unnecessarily copy the entire container. You can avoid this and still use the pretty for syntax with C ++ 17 std::as_const :

 for (auto const& c : std::as_const(vc)) std::cout << c; 

You can easily implement your own version of as_const if your environment does not provide it.

+1
source

All Articles