Why and when to use constexpr

In today's article I just want to briefly cover why and when you would use the keyword constexpr. Constexpr was introduced in C++11 and is used to tell the compiler: it may be possible to evaluate this expression at compile time. As an example:
Here we have a recursive function which calculates the Fibonacci number at position n in the sequence. Now we need to ask ourselves, can this computation be carried out at compile time? Well, the answer is yes it can, if we know the value of n at compile time. Lets take the above example a bit further, lets say we want the Fibonacci number at position 6 in the sequence: Now, to properly demonstrate the power of compile time optimisations and the importance of making use of them as best we can in our code I'm going to use a tool I started using recently called compiler explorer. Compiler explorer let's us enter code snippets and view the assembly output generated by the compiler. I won't pretend to be an expert in assembly as I'm still fairly new to programming with C++ and have never had to read it before, however, I'm taking the approach that less is more. So, let's take a look at our code snippet in compiler explorer: So, our code is in the left column and the compiled output is on the right. For this example I'm using gcc 7.3 with the compiler optimisation level set to 2. If you're interested you can read a bit more about the optimisation levels here. So, as you can see we've got 62 lines of assembly (which I won't attempt to explain at this point as I'm still learning to read assembler myself). Now let's see what happens when we apply constexpr to our function definition: As you can see, we've gone from 62 lines of assembly to just 22. We've completely removed the need to calculate the Fibonacci number at run-time as the compiler has done that work for us. As you can see on line 3 we move the value of 8 (the Fibonacci number we're looking for) into the esi register, so the compiler has calculated our value at compile time and hard coded it into our assembly output. This is obviously a fairly trivial example which may not have cost much in the way of performance to calculate at run-time, but just imagine if we had to make many of these calculations, or if we had to calculate the Fibonacci number for a large value.

Constexpr can be applied to more than just functions, you can apply constexpr to variable declarations and even constructors. You can read more about constexpr here.

In summary, why constexpr? Having the ability to shift the work from the program's run-time into compile time is extremely powerful and can certainly help improve run-time performance. And when constexpr? whenever possible!

Comments

  1. Cool! Thanks for the explanation. I'm new to C++, so if you know any ways to practice c++ for beginners it would be nice to hear.

    ReplyDelete

Post a Comment

Popular posts from this blog

Err.exe: A Tool for Error Code Lookup

RAII: Resource Acquisition is Initialisation