web-dev-qa-db-fra.com

Quelle est la différence entre les variables constexpr statiques et statiques en ligne en C ++ 17?

Avec C++ 17, nous obtenons des variables en ligne.

L'une d'elles est de définir des champs constants dans les classes.

Quelle est donc la différence entre ces deux définitions constantes:

class MyClass {
    static constexpr int myFirstVar = 10;
    static const inline int mySecondVar = 100;
};

Bien sûr, constexpr rend myFirstVar implicitement en ligne.

Quel est le meilleur choix ici, pour utiliser constexpr ou inline?

Remarque: lorsque vous n'avez pas besoin de constance, alors inline vous facilite la tâche. Avec constexpr, vous n'avez pas ce choix.

47
fen

Vous n'avez pas besoin de spécifier un initialiseur pour mySecondVar au point de déclaration. Il n'est pas non plus nécessaire que l'initialiseur soit constexpr lui-même.

Cela signifie que si nous essayons de définir myFirstVar comme ceci:

class MyClass {
    static constexpr int myFirstVar;
};

int MyClass::myFirstVar = 1;

Ou comme ça:

#include <cstdlib>

class MyClass {
    static constexpr int myFirstVar = Rand();
};

Il est mal formé de toute façon. constexpr la sémantique l'exige et pour une bonne raison.

L'approche de spécificateur inline nous permet d'inclure une définition de variable statique dans l'en-tête lui-même, sans que l'initialiseur soit constexpr; ou si l'initialiseur est assez complexe, il n'a pas besoin d'être dans la définition de classe elle-même.

Voici donc un en-tête parfaitement valide en C++ 17:

#include <cstdlib>

class MyClass {
    static const int mySecondVar;
};

inline const int MyClass::mySecondVar = Rand();

La norme nous promet que toutes les unités de traduction qui incluent l'en-tête verront la même valeur pour la variable, même si nous ne saurons pas ce que c'est avant l'exécution.

C'est surtout un outil d'écrivain de bibliothèque. Supposons que votre bibliothèque soit uniquement en-tête. Alors dans les temps anciens, quelles étaient vos options si vous aviez besoin d'une constante statique définie comme ceci?

Eh bien, vous pourriez avoir un fichier objet livré avec votre bibliothèque. Il sera compilé à partir d'une unité de traduction qui contient uniquement la définition constante. Maintenant, la bibliothèque n'est pas uniquement en-tête.

Ou vous pouvez plutôt compter sur des fonctions en ligne. L'effet variable en ligne peut être obtenu avec les éléments suivants:

class MyClass {
    static inline int mySecondVar();
};

inline int MyClass::mySecondVar() {
  static const int value = Rand();
  return value;
}

Mais il est caché derrière un mur de syntaxe et masque ce qui est essentiellement une constante, avec un opérateur d'appel de fonction.

49
StoryTeller