Est-il préférable d'utiliser static const
vars que #define
préprocesseur? Ou peut-être que cela dépend du contexte?
Quels sont les avantages/inconvénients pour chaque méthode?
Personnellement, je déteste le préprocesseur, donc je vais toujours avec const.
Le principal avantage de #define est qu’elle ne nécessite aucune mémoire pour être stockée dans votre programme, car elle remplace en réalité un texte par une valeur littérale. Il a également l'avantage de ne pas avoir de type et qu'il peut donc être utilisé pour toute valeur entière sans générer d'avertissements.
Les avantages des "const" sont qu'ils peuvent être étendus et peuvent être utilisés dans des situations où un pointeur sur un objet doit être passé.
Je ne sais pas exactement où vous voulez en venir avec la partie "statique". Si vous déclarez globalement, je le mettrais dans un espace de nom anonyme au lieu d'utiliser statique. Par exemple
namespace {
unsigned const seconds_per_minute = 60;
};
int main (int argc; char *argv[]) {
...
}
Avantages et inconvénients de tout, en fonction de l'utilisation:
enum class X
sont non ambiguës par la portée X::
int
mais peut être défini explicitement par le programmeurtemplate <typename T> void f(T t) { cout << ++t; }
ne compilera pas, bien que vous puissiez envelopper une énumération dans une classe avec un constructeur implicite, un opérateur de transtypage et des opérateurs définis par l'utilisateur)template <typename T> void f(T)
obtient une instanciation distincte lorsque la même valeur numérique est passée à partir de différentes énumérations, qui sont toutes distinctes de toute instanciation f(int)
réelle. Le code objet de chaque fonction peut être identique (en ignorant les décalages d'adresse), mais je ne m'attendrais pas à ce qu'un compilateur/éditeur de liens élimine les copies inutiles, bien que vous puissiez vérifier votre compilateur/éditeur de liens si vous le souhaitez.enum { A = 1, B = 2 }
- est A|B
"légal" à partir d’un perspective du programme?)make
et d'autres outils de recompilation basés sur un horodatage déclenchent la recompilation du client lorsqu'ils sont modifiés (mauvais !)#define
ala #define S std::string("abc")
, mais la constante évite la construction répétée de temporaires distincts à chaque point d'utilisationconst
, ce qui minimise le travail et l’impact si la commutation entre les deux#define X "x"
et une certaine utilisation du client ala "pre" X "post"
, si vous voulez ou devez faire de X une variable modifiable à l’exécution plutôt que constante, vous forcez les modifications au code client (plutôt que la simple recompilation), alors que cette transition est plus facile à partir d'un const char*
ou const std::string
étant donné qu'ils obligent déjà l'utilisateur à incorporer des opérations de concaténation (par exemple, "pre" + X + "post"
pour string
)sizeof
){ 1, 2 }
pouvant être utilisées pour initialiser des tableaux, ou #define MICROSECONDS *1E-6
etc. ( définitivement ne le recommandant pas!)__FILE__
et __LINE__
peuvent être incorporées dans la substitution de macros#if
pour l'inclusion conditionnelle de code (plus puissant qu'un "si" de post-traitement préalable, car le code n'a pas besoin d'être compilable s'il n'est pas sélectionné par le pré-processeur), utilisez #undef
-ine, redéfinissez, etc.unsigned
et d'autres outils de recompilation basés sur l'horodatage déclencheront une recompilation du client quand ils seront modifiés (mauvais!)make
s et je les considère comme l'option la plus professionnelle pour un usage général (même si les autres ont une simplicité qui séduit ce vieux programmeur paresseux).As a general rule, I use const
s and consider them the most professional option for general usage (though the others have a simplicity appealing to this old lazy programmer).
S'il s'agit d'une question C++ et qu'elle mentionne #define
en guise d'alternative, il s'agit alors de constantes "globales" (c'est-à-dire de la portée du fichier) et non de membres de la classe. En ce qui concerne de telles constantes en C++, static const
est redondant. En C++, const
a un lien interne par défaut et il est inutile de les déclarer static
. Donc, il s’agit vraiment de const
contre #define
.
Et, finalement, en C++, const
est préférable. Du moins parce que ces constantes sont typées et étendues. Il n'y a tout simplement aucune raison de préférer #define
à const
, à quelques exceptions près.
Les constantes de chaîne, BTW, sont un exemple d'une telle exception. Avec les constantes de chaîne #define
d, on peut utiliser la fonctionnalité de concaténation au moment de la compilation des compilateurs C/C++, comme dans
#define OUT_NAME "output"
#define LOG_EXT ".log"
#define TEXT_EXT ".txt"
const char *const log_file_name = OUT_NAME LOG_EXT;
const char *const text_file_name = OUT_NAME TEXT_EXT;
P.S. Encore une fois, juste au cas où, quand quelqu'un mentionne static const
comme alternative à #define
, cela signifie généralement qu'ils parlent de C, pas de C++. Je me demande si cette question est étiquetée correctement ...
Utiliser un const statique revient à utiliser n'importe quelle autre variable const dans votre code. Cela signifie que vous pouvez suivre d'où provient l'information, par opposition à une #define qui sera simplement remplacée dans le code lors du processus de pré-compilation.
Vous voudrez peut-être jeter un coup d'œil à la version C++ FAQ pour cette question: http://www.parashift.com/c++-faq-lite/newbie.html#faq-29.7
Habituellement, vous devriez préférer les constants statiques. Cela n'a pas d'inconvénient. Le pré-processeur devrait être principalement utilisé pour la compilation conditionnelle (et parfois pour des trics vraiment sales).
La définition de constantes à l'aide de la directive de préprocesseur #define
n'est pas recommandée pour s'appliquer non seulement dans C++
, mais également dans C
. Ces constantes n'auront pas le type. Même dans C
, il a été proposé d'utiliser const
pour les constantes.
#define
peut conduire à des résultats inattendus:
#include <iostream>
#define x 500
#define y x + 5
int z = y * 2;
int main()
{
std::cout << "y is " << y;
std::cout << "\nz is " << z;
}
Affiche un résultat incorrect:
y is 505
z is 510
Cependant, si vous remplacez cela par des constantes:
#include <iostream>
const int x = 500;
const int y = x + 5;
int z = y * 2;
int main()
{
std::cout << "y is " << y;
std::cout << "\nz is " << z;
}
Il produit le résultat correct:
y is 505
z is 1010
En effet, #define
remplace simplement le texte. Parce que cela peut sérieusement gâcher l'ordre des opérations, je recommanderais plutôt d'utiliser une variable constante.
S'il vous plaît voir ici: static const vs define
généralement une déclaration const (notez qu'il n'est pas nécessaire qu'elle soit statique) est la voie à suivre
Préférez toujours utiliser les fonctionnalités du langage par rapport à certains outils supplémentaires tels que le préprocesseur.
ES.31: n'utilisez pas de macros pour des constantes ou des "fonctions"
Les macros sont une source majeure de bugs. Les macros n'obéissent pas à la portée habituelle et règles de type. Les macros n'obéissent pas aux règles habituelles d'argumentation qui passe. Les macros garantissent que le lecteur humain voit quelque chose de différent de ce que voit le compilateur. Les macros compliquent la construction des outils.
From C++ Core Guidelines
Si vous définissez une constante à partager entre toutes les instances de la classe, utilisez static const. Si la constante est spécifique à chaque instance, utilisez simplement const (mais notez que tous les constructeurs de la classe doivent initialiser cette variable membre const dans la liste d'initialisation).