Skip to content
C++ Better Explained
Go back
C++ const vs constexpr: What's the Difference?
Edit page

C++ const vs constexpr: What’s the Difference?

Both const and constexpr mean “this value doesn’t change.” But they differ in one important way: when the value is determined.


const: Value Fixed After Initialization

A const variable’s value is fixed once assigned — but the assignment can happen at runtime:

const int x = 5;          // Compile-time — value known immediately
const int y = x * 2;      // Also compile-time — computed from x

int n;
cin >> n;
const int z = n;          // Runtime — value determined by user input
                           // Still const (can't change), but not compile-time

const means “don’t change this value.” It says nothing about when the value is determined.


constexpr: Value Guaranteed at Compile Time

A constexpr variable must be fully determined at compile time:

constexpr int x = 5;      // Fine — 5 is a compile-time constant
constexpr int y = x * 2;  // Fine — x is constexpr, so x*2 is too

int n;
cin >> n;
constexpr int z = n;      // Error! n is runtime — not compile-time

If you try to initialize a constexpr with a runtime value, the compiler gives an error. This is the guarantee: constexpr values are always available at compile time.


Why Compile-Time Constants Matter

Several C++ features require compile-time constants:

Array sizes:

const int n = 5;       // May or may not work as array size (implementation-defined for local const int)
constexpr int m = 5;   // Always works

int arr[m];            // Fine — m is a compile-time constant

Template arguments:

constexpr int SIZE = 100;
array<int, SIZE> data;      // Fine — constexpr as template arg
bitset<SIZE> flags;         // Fine

const int RUNTIME_SIZE = getSizeFromFile();
array<int, RUNTIME_SIZE> bad;  // Error — not compile-time

static_assert:

constexpr int MAX_USERS = 1000;
static_assert(MAX_USERS > 0, "Must have at least one user");  // Checked at compile time

constexpr Functions

A constexpr function can be evaluated at compile time if called with compile-time arguments, or at runtime otherwise:

constexpr int square(int x) {
    return x * x;
}

constexpr int a = square(5);    // Evaluated at compile time → a = 25
int b = square(7);              // Evaluated at runtime — still works

int n;
cin >> n;
int c = square(n);              // Runtime — n is not compile-time

Compile-time vs runtime behavior:

constexpr int factorial(int n) {
    return (n <= 1) ? 1 : n * factorial(n - 1);
}

constexpr int f5 = factorial(5);  // Computed at compile time — no runtime cost
// f5 is literally 120 in the compiled binary

int x = 10;
int fx = factorial(x);            // Computed at runtime (x is not constexpr)

This flexibility makes constexpr functions powerful — write once, works in both contexts.


const vs constexpr for Member Functions

In a class, const on a member function means “this function doesn’t modify the object.” constexpr member functions can additionally be evaluated at compile time:

class Circle {
    double radius;
public:
    constexpr Circle(double r) : radius(r) {}  // constexpr constructor

    constexpr double area() const {            // constexpr + const
        return 3.14159 * radius * radius;
    }
};

constexpr Circle c(5.0);
constexpr double a = c.area();  // Computed at compile time!

When to Use Each

Use const when:

void printName(const string& name) { ... }  // const parameter reference
const int maxAttempts = getConfigValue();    // Runtime value, but immutable

Use constexpr when:

constexpr double PI = 3.14159265358979;
constexpr int MAX_SIZE = 256;
constexpr int KB = 1024;
constexpr int MB = 1024 * KB;
If you're looking to go deeper with C++, the C++ Better Explained Ebook is perfect for you — whether you're a complete beginner or looking to solidify your understanding. Just $19.

consteval (C++20): Always at Compile Time

C++20 added consteval for functions that must always be evaluated at compile time (unlike constexpr which can run at runtime too):

consteval int mustBeCompileTime(int x) {
    return x * x;
}

constexpr int a = mustBeCompileTime(5);  // Fine — compile time
int x = 10;
int b = mustBeCompileTime(x);           // Error — x is runtime!

Summary

constconstexpr
Value doesn’t changeYesYes
Compile-time requiredNoYes
Works with runtime valuesYesNo
Can be array sizeSometimesAlways
Can be template argSometimesAlways
Applies to functionsYes (means “no mutation”)Yes (enables compile-time eval)

The practical rule: if the value is a true constant that the compiler can know (like PI or buffer sizes), use constexpr. If the value is just “don’t change this after I set it” — especially from runtime sources — use const.



Take Your C++ Further

If you’re looking to go deeper with C++, the C++ Better Explained Ebook is perfect for you — whether you’re a complete beginner or looking to solidify your understanding. Just $19.

👉 Get the C++ Better Explained Ebook — $19

📋

Free Download: The 10 Mistakes Every C++ Beginner Makes

A free 1-page checklist that shows the exact traps that slow down every C++ beginner — so you can avoid them from day one.

🔒 No spam. Unsubscribe anytime.


Edit page
Share this post on:

Previous Post
C++ Array vs Vector: Which One Should You Use?
Next Post
C++ Constructors and Destructors Explained