ProgrammationDéveloppeur C++

Que sont les const-expressions (constexpr) en C++ ? Dans quels cas et pourquoi les utiliser, et en quoi diffèrent-elles des macros et du const ?

Réussissez les entretiens avec l'assistant IA Hintsage

Réponse

Historique

C++ ne supportait initialement que les macros (#define) et les constantes (const). Cependant, pour définir des valeurs au moment de la compilation, cela n'était pas suffisant. En C++11, le mot-clé constexpr a été introduit, permettant de calculer des valeurs même au moment de la compilation, et non seulement lors de l'exécution du programme.

Problème

Avant l'apparition de constexpr, de nombreuses tâches devaient être résolues soit par des macros (un substitut de texte brut sans sécurité de type), soit par const, qui ne garantissait pas toujours l'exécution de l'expression au moment de la compilation. Cela compliquait l'optimisation du programme et conduisait à un comportement moins prévisible.

Solution

constexpr garantit au compilateur que l'expression déclarée sera nécessairement calculée au moment de la compilation, si cela est possible. Cela est utilisé pour déclarer des fonctions, des variables et même des constructeurs et des méthodes de classes qui peuvent être calculés de manière sûre et efficace au moment de la compilation.

Exemple de code :

constexpr int Square(int x) { return x * x; } constexpr int size = Square(5); // size est calculé au moment de la compilation const int arr[size] = {}; // peut être utilisé comme taille de tableau

Caractéristiques clés :

  • Permet le calcul au moment de la compilation (si possible).
  • Permet de déclarer non seulement des variables, mais également des fonctions, des méthodes et des constructeurs.
  • Améliore les performances grâce aux calculs précoces et à la sécurité des types.

Questions pièges.

Peut-on utiliser n'importe quelle fonction comme constexpr ?

Non. La fonction doit respecter un certain nombre de contraintes : être suffisamment simple, contenir une seule instruction de retour (jusqu'à C++14) ou uniquement du code calculable de manière constante (à partir de C++14 et plus).

constexpr int f(int x) { return x + 2; } // ok constexpr int g(int x) { int y = x + 2; return y; } // jusqu'à C++14 : ne compile pas ! après — c'est possible

Toutes les variables constexpr peuvent-elles être calculées au moment de la compilation ?

Non. Si une valeur non constante est utilisée lors de l'initialisation ou si l'expression ne peut pas être calculée lors de la compilation, une erreur se produira.

int val; // constexpr int x = f(val); // Erreur : val n'est pas initialisé !

Quelle est la différence entre constexpr et const ?

const garantissant seulement l'impossibilité de modification, mais ne garantissant pas le calcul au moment de la compilation. constexpr exige que la valeur soit calculée au moment de la compilation (si possible).

const int x = time(nullptr); // ok, mais calculé au moment de l'exécution constexpr int y = 42; // ok, calculé au moment de la compilation

Erreurs courantes et anti-pix

  • Confusion entre const et constexpr
  • Essayer d'utiliser des constructions logiques complexes dans une fonction constexpr avant C++14
  • Mauvaise utilisation de variables non constantes dans un contexte constexpr

Exemple de la vie réelle

Cas négatif

Un développeur utilise #define PI 3.14 pour tous les calculs de surface de cercle.

Avantages :

  • Facile à écrire

Inconvénients :

  • Pas de sécurité de type, risque d'erreur de substitution
  • Ne peut pas être utilisé comme constexpr dans des modèles ou des paramètres de tableau

Cas positif

Un développeur utilise constexpr double PI = 3.141592653589793; et des fonctions constexpr modèles pour les calculs.

Avantages :

  • Sécurité de type
  • Optimisation à la compilation
  • Polyvalence d'utilisation (par exemple, dans des templates).

Inconvénients :

  • Exige une légère compréhension supplémentaire du code ; prise en charge requise de C++11+