C++ has a couple quite unique properties: zero-cost abstractions and backward compatibility. While those properties are not perfectly followed in C++, the commitment to achieving them remains strong.
Iteration in Pre-C++11
Before C++11, there were few common ways to iterate over a collection (std::vector specifically). One of them is to use C++'s iterators:
for (
std::vector<Employee>::const_iterator it = begin(input);
it != end(input);
it++
) {
if (it->job == "programmer")
names.push_back(it->name);
}
The iterators provide a unified (unified is a buzzword recently) way to traverse over all types of collections. In C++, iterators are zero-cost abstraction, meaning developers incur (almost?) no performance overhead when using them. However, despite their universality, simply using indices can make the code more concise, since the type of the iterator is quite cumbersome to type:
for (int ii = 0; ii < input.size(); ++ii) {
const Employee& element = input[ii];
if (element.job == "programmer")
names.push_back(element.name);
}
Note: Using double "i" is an old-school way of defining an "i", which is very easy to search for in any text editor.
C++11 is like a new language!
In C++11, we've got so many improvements, that it feels almost like a new language.
With introduction of auto, one can simply avoid writing the iterator type:
for (auto it = begin(input); it != end(input); it++) {
if (it->job == "programmer")
names.push_back(it->name);
}
Yes, the only difference is std::vector<Employee>::const_iterator
was replaced with auto
. Despite the not-quite-trivial type deduction rules, auto
is very good default option for very verbose names.
Also, C++11 brings range-based for loops, what makes the life so much easier:
for (const auto& element: input) {
if (element.job == "programmer")
names.push_back(element.name);
}
Bottom Line
The range-base for loop is an alternative syntax for the iterator-based approach and requires the collection to be "iterable", i.e. implement speicific properties of a collection and iterator types.
The range-based for loop is implemented using C++'s iterators. The iterators are implemented using concrete types without extra overhead. The iterator implementation as efficient as the low-level code. The range-based for loop is a perfect example of zero-cost abstraction. Also, each of the ways of iterating over a collection would likely lead to nearly identical assembly code. And each way still works on newest compilers!