DEV Community

Cover image for const and constexpr
MinBapE
MinBapE

Posted on

const and constexpr

Introduction

While working on a personal project, I learned about constexpr. I understood the difference between const and constexpr. However, I wondered why constexpr is necessary when const seems sufficient. I want to share what I found in this article.


const

A keyword that promises the compiler that a value cannot be changed.
Once initialized, the value cannot be modified.

const int MAX_USERS = 100;
MAX_USERS = 200;  // Compilation error!
Enter fullscreen mode Exit fullscreen mode

Characteristics

  • The initialization value can be known at compile time or at runtime.
int A;
std::cin >> A;
const int B = A;  // Valid
// Constant B is determined at runtime, but cannot be changed afterwards.
// The value doesn't need to be known at compile time, but once set, it cannot be changed.
Enter fullscreen mode Exit fullscreen mode
  • It becomes more powerful when used with references and pointers.
const int* ptr1;        // Cannot change the pointed value
int* const ptr2;        // Cannot change the pointer itself
const int* const ptr3;  // Cannot change both
Enter fullscreen mode Exit fullscreen mode
  • When const is added to a class member function, the function promises not to change the object's state.
class User {
private:
    std::string name;
    int age;
public:
    // Does not modify member variables
    std::string getName() const {
        return name;
        // age = 30;  // Error occurs
    }

    void setAge(int newAge) {
        age = newAge; // Valid
    }
};
Enter fullscreen mode Exit fullscreen mode

Limitations

  • If a member variable is declared as mutable, it can be modified even in const member functions.
  • const can be forcibly removed using const_cast.

constexpr

constexpr is short for "constant expression".
Unlike const, it is a keyword that guarantees the compiler that the value is determined at compile time.
It was first introduced in C++11, and most restrictions have been lifted through version updates.

constexpr int func(int n) {
    return n * n;
}
constexpr int A = 1;        // Initialized to 1 at compile time
constexpr int B = func(2);  // Calculated to 4 at compile time
constexpr int C = func(B);  // Calculated to 16 at compile time
Enter fullscreen mode Exit fullscreen mode

The critical difference from const is as follows:

int func() { 
    int value;
    std::cin >> value;
    return value;
}
const int a = func();      // Valid -> because it's determined at runtime
constexpr int b = func();  // Error occurs
Enter fullscreen mode Exit fullscreen mode

Reasons to Use

  • Performance is improved as complex calculations can be completed at compile time through compile-time computation.
  • In C++, array sizes and template arguments must be compile-time constants.
  • Incorrect calculations can be caught before execution.
  • The compiler can perform more verification.
// 1. Performance improvement
constexpr int factorial(int n) {
    return (n <= 1) ? 1 : n * factorial(n - 1);
}
constexpr int result = factorial(10);  // Zero calculation cost at runtime

// 2. Array size
constexpr int SIZE = 100;
int buffer[SIZE];  // OK

const int size = getSize();
int arr[size];  // Error in most cases

// 3. Compile-time verification
constexpr int divide(int a, int b) {
    return b == 0 ? throw "error" : a / b;
}
constexpr int x = divide(10, 0);  // Compilation error occurs
Enter fullscreen mode Exit fullscreen mode

When to Use const vs constexpr?

When to use const

  • Use when the value can be known at runtime, such as user input, configuration values read from files.
  • Use const to express the intention not to modify arguments passed to a function.
  • Member functions that do not change the object's state should be declared as const.

When to use constexpr

  • C++ array sizes must be compile-time constants.
  • Template parameters must be determined at compile time.
  • Use when you want to pre-calculate complex computations.
  • Use in switch statement case labels, static_assert, etc.
Situation const constexpr
User input value O X
Array size O
Template argument X O
Function parameter O X
Compile-time calculation O

Summary

const is a promise of immutability, and constexpr is a guarantee of compile-time calculation.
const can accept runtime values, but constexpr is determined only at compile time.

Top comments (0)