Expert C++
上QQ阅读APP看书,第一时间看更新

Loops

Loops may be perceived as repeatable if statements, which again should be translated into CPU comparison and jump instructions. For example, we can calculate the sum of numbers from 0 to 10 using the while loop:

auto num = 0;
auto sum = 0;
while (num <= 10) {
sum += num;
++num;
}

This will translate to the following assembly code (simplified):

mov rax, 0; the sum
mov rcx, 0; the num
LOOP:
cmp rbx, 10
jg END; jump to the END if num is greater than 10
add rax, rcx; add to sum
inc rcx; increment num
jmp LOOP; repeat
END:
...

C++17 introduced init statements that can be used in conditionals and loops. The num variable declared outside of the while loop may now be moved into the loop:

auto sum = 0;
while (auto num = 0; num <= 10) {
sum += num;
++num;
}

The same rule applies to the if statement, for example:

int get_absolute(int num) {
if (int neg = -num; neg < 0) {
return -neg;
}
return num;
}

C++11 introduced the range-based for loop, which makes the syntax much clearer. For example, let's call all the arithmetic operations we defined earlier using the new for loop:

for (auto& op: operations) {
std::cout << op.second(num1, num2);
}

Iterating  unordered_map returns a pair with the first and second members, the first being the key, and the second being the value mapped to that key. C++17 moved us even further, allowing us to write the same loop as follows:

for (auto& [op, func]: operations) {
std::cout << func(num1, num2);
}

Knowing what the compiler actually generates is key in designing and implementing efficient software. We touched on the low-level details of conditionals and loops, which are at the base of almost every program.