for loops are a powerful tool in C/C++, they are one of the desirable tools when you want to do something repeatedly, or process elements of a data structures. But there many ways to write a
for loop. Some forms of it are easier to use, read, write and understand, and some are not. Range based
for loops are discussed in this article. They can be good if you know where to use them.
Range Based For Loops
Since C++11, range based
for loops are available to iterate over a known
range of values. For example, when there is a need to process elements
of a container, range based loops are usually a good choice. They are
easy to write, read and understand.
The simplest form is as below, but be warned that it is not usually good:
for(auto variable : range)
In this way, a temporary variable is created to iterate over the range of values. But this is usually undesirable, because the a copy of the variable is created each time.
When you need to modify the values of the elements, you should use a reference:
for(auto &variable : range)
This is also useful for working on big elements, as it can speed up the code by avoiding unneeded copying.
If modifying the elements is not needed, it is possible to use the reference, but use
const to prevent modification of the referenced object. This is an example:
for(auto const &element : range)
This is usually called east
const. The latter is semantically equivalence, but is called west
for(const auto &element : range)
element itself can not be changed, and that is also true for references to non-pointer objects.
There are other variants that are discussed in Auto Type Deduction in Range-Based For Loops.
Declaring Variable Type
You can use
auto to let C++ compiler decide the suitable type for the loop variable, but you can also declare the variable type explicitly instead of using
auto. Both of them are acceptable.
For a good example, see this commit from Michael Weghorn:
Sequence pStates = pRState->getStates();
int count = pStates.getLength();
for( int iIndex = 0;iIndex < count;iIndex++ )
if (pStates[iIndex] == AccessibleStateType::MANAGES_DESCENDANTS)
is converted into this range based for loop:
for (sal_Int16 nState : pRState->getStates())
if (nState == AccessibleStateType::MANAGES_DESCENDANTS)
Limitations of Range Based For Loops
Range based loops can simplify the code, but there are limitations for them. For example, if there is a need not to skip certain values, you will need
std::ranges::views::drop which is available in C++20. Thus, they are not suitable for replacing every normal for loop.
For an init statement in the range based for loop, you will also need C++20.
EasyHacks are a good start for newcomers. This specific improvement is filed as tdf#145538.
You can find some possible candidates for changing to range based for loops with these commands:
$ git grep -w for *.cxx | grep -iF "size()"
$ git grep -w for *.cxx | grep -iF "length()"
Good candidates can be found among the results.
If you want to contribute to LibreOffice code by working on this improvement, but you need to know how to get started with LibreOffice development, I suggest you to see our video tutorial:
Getting Started (Video Tutorial)