C using move semantics
In which I briefly mention what pure functional programming is, explain why this can be slow in C++, and use move semantics to solve that problem. Be warned that this post is a bit longer than usual for this blog, and that it assumes more knowledge of C++11 than my posts usually do.
Pure functional programming is programming without state. In short, functions should not modify their input, not modify local or global state, but return new values instead. Often, we also want to avoid variables completely.
For instance, instead of doing:
void square(vector& v) { /*multiply each element with itself*/ } void imperative { vector v = getNumbers; square(v); doStuffWith(v); }
we do
vector squared(const vector& v) { /*return a new vector with squared elements*/ } void functional { doStuffWith( squared( getNumbers)); }
As you might already have noticed, this style results in more copies than the imperative style, which will lead to less efficient code. Depending on the problem you are solving, this might or might not matter, but one of the few real arguments for using C++ is that you have a problem that needs an efficient solution.
Let’s take a look at an example program, translate it from imperative to functional style, and finally use move semantics (explained later) to eliminate the performance hit. For our example, we will compute the root mean square of a function. Wikipedia has a good definition, but in short: Given a list of numbers, square each of them, take the mean of those squares, and return the square root of that number.
First, let’s define some helper functions:
double sum(const std::vector& v) { return std::accumulate(v.begin, v.end, 0, std::plus); } double mean(const std::vector& v) { return sum(v) / v.size; }
The square root function already exists as std::sqrt, so we don’t need to define that. The only missing piece is a function computing the square of a vector of numbers. In good old C++, there are two ways of doing this:
vector square(vector v); //(Or the argument could be a const reference) void square(vector& v);
The first version creates a copy of the vector, containing the squared number. This is perfect for functional code, but makes a copy that might be unnecessary. The second version modifies the argument, which is faster and often seen in imperative code. Since we assume we want efficiency, we’ll go with the second one in the examples that follow.
You might also like
Sammons preston Library of Early/Emergent Vocabulary Photographs Health and Beauty (Sammons preston)
|