Lesson 3
STL Algorithms: Part 2
Lesson Introduction

Welcome back! In our previous lesson, we explored the fundamentals of STL algorithms in C++ and how they can enhance your code's efficiency and readability. Today, we will continue this journey by diving into more advanced STL algorithms, with a focus on std::accumulate.

By the end of this lesson, you should understand:

  1. How to use std::accumulate to find the sum of numbers in a vector.
  2. Advanced uses of std::accumulate with custom functionalities using lambda expressions.
Understanding `std::accumulate`

std::accumulate in the <numeric> header performs a fold or reduction operation over a range of elements. It combines the elements using a binary operation, starting with an initial value.

The basic syntax of std::accumulate:

C++
1std::accumulate(first, last, init);
  • First: Iterator to the beginning of the range.
  • Last: Iterator to the end of the range.
  • Init: Initial value to start the accumulation.
Example of Using `std::accumulate`

Here is an example using std::accumulate to sum the elements of a vector:

C++
1#include <iostream> 2#include <vector> 3#include <numeric> // For std::accumulate 4 5int main() { 6 std::vector<int> data = {1, 2, 3, 4, 5}; 7 8 // Using std::accumulate 9 int sum = std::accumulate(data.begin(), data.end(), 0); 10 std::cout << "Sum: " << sum << '\n'; // Sum: 15 11 12 return 0; 13}

Explanation:

  1. Initialize a vector: We initialize a vector data with {1, 2, 3, 4, 5}.
  2. Use std::accumulate: We pass the range defined by data.begin() and data.end(), and the initial value 0.
  3. Result: The function sums the elements starting from 0. The final sum, 15, is outputted.
Advanced Use of `std::accumulate`

Consider computing the product of elements:

C++
1#include <iostream> 2#include <vector> 3#include <numeric> // For std::accumulate 4#include <functional> // For std::multiplies 5 6int main() { 7 std::vector<int> data = {1, 2, 3, 4, 5}; 8 9 // Using std::accumulate with std::multiplies 10 int product = std::accumulate(data.begin(), data.end(), 1, std::multiplies<int>()); 11 std::cout << "Product: " << product << '\n'; // Product: 120 12 13 return 0; 14}

Explanation:

  1. Initial Value: Use 1 as the initial value.
  2. Custom Operation: Use std::multiplies<int>() for multiplication.
Using Lambda Expressions: Sum of Squares

Let's look at custom logic with lambda expressions.

Finding the Sum of Squares:

C++
1#include <iostream> 2#include <vector> 3#include <numeric> // For std::accumulate 4 5int main() { 6 std::vector<int> data = {1, 2, 3, 4, 5}; 7 8 // Using std::accumulate with a lambda expression 9 int sum_of_squares = std::accumulate(data.begin(), data.end(), 0, [](int sum, int val) { 10 return sum + val * val; 11 }); 12 std::cout << "Sum of Squares: " << sum_of_squares << '\n'; // Sum of Squares: 55 13 14 return 0; 15}

Custom Lambda: We pass a lambda that computes the square of each element and adds it to the sum. In the lambda expression:

  • sum: Accumulator that holds the ongoing sum of squares.
  • val: Current element from the vector being processed.
Using Lambda Expressions: Combining Vectors

Combining two vectors into a single accumulated sum:

C++
1#include <iostream> 2#include <vector> 3#include <numeric> // For std::accumulate 4 5int main() { 6 std::vector<int> data1 = {1, 2, 3, 4, 5}; 7 std::vector<int> data2 = {6, 7, 8, 9, 10}; 8 9 // Combining two vectors element-wise and accumulating the result 10 int combined_sum = std::accumulate(data1.begin(), data1.end(), 0, [&data2, i = 0](int sum, int val) mutable { 11 return sum + val + data2[i++]; 12 }); 13 std::cout << "Combined Sum: " << combined_sum << '\n'; // Combined Sum: 55 14 15 return 0; 16}

Lambda with Capture: We capture data2 by reference and use a mutable lambda to add elements of both vectors. In the lambda expression:

  • sum: Accumulator that holds the ongoing sum of combined elements from both vectors.
  • val: Current element from data1 being processed.
  • data2[i++]: Corresponding element from data2 being added, with mutable allowing us to modify the captured i to iterate through data2.
Lesson Summary

In this lesson, we explored:

  • The importance and utility of STL algorithms in C++.
  • How to use std::accumulate for simple and complex operations.
  • Examples with built-in and custom operations via lambda expressions.

Now that you've learned to use std::accumulate, it's time to practice. Move on to the hands-on exercises to reinforce your understanding and enhance your skills. Good luck, and happy coding!

Enjoy this lesson? Now it's time to practice with Cosmo!
Practice is how you turn knowledge into actual skills.