Ist es besser, static const
vars als #define
Präprozessor zu verwenden? Oder hängt es vielleicht vom Kontext ab?
Was sind Vor- und Nachteile für jede Methode?
Ich persönlich verabscheue den Präprozessor, also würde ich immer mit const gehen.
Der Hauptvorteil von #define besteht darin, dass in Ihrem Programm kein Speicherplatz erforderlich ist, da es wirklich nur Text durch einen Literalwert ersetzt. Es hat auch den Vorteil, dass es keinen Typ hat, sodass es für jeden ganzzahligen Wert verwendet werden kann, ohne dass Warnungen generiert werden.
Die Vorteile von "const" sind, dass sie eingeschränkt werden können, und sie können in Situationen verwendet werden, in denen ein Zeiger auf ein Objekt übergeben werden muss.
Ich weiß nicht genau, was Sie mit dem "statischen" Teil anfangen. Wenn Sie global deklarieren, würde ich sie in einen anonymen Namespace stellen, anstatt statisch zu verwenden. Zum Beispiel
namespace {
unsigned const seconds_per_minute = 60;
};
int main (int argc; char *argv[]) {
...
}
Vor- und Nachteile für alles, je nach Nutzung:
enum class X
durch den Gültigkeitsbereich X::
eindeutig sind.int
ist, aber vom Programmierer explizit festgelegt werden kanntemplate <typename T> void f(T t) { cout << ++t; }
wird nicht kompiliert, obwohl Sie eine Enumeration in eine Klasse mit implizitem Konstruktor, Casting-Operator und benutzerdefinierten Operatoren einschließen können)template <typename T> void f(T)
eine eindeutige Instanziierung erhält, wenn derselbe numerische Wert aus verschiedenen Aufzählungen übergeben wird, die sich alle von jeder tatsächlichen f(int)
Instanziierung unterscheiden. Der Objektcode jeder Funktion könnte identisch sein (Adress-Offsets werden ignoriert), aber ich würde nicht erwarten, dass ein Compiler/Linker die unnötigen Kopien eliminiert, obwohl Sie Ihren Compiler/Linker überprüfen könnten, wenn Sie sich darum kümmern.enum { A = 1, B = 2 }
- is A|B
"legal" aus programmlogischer Sicht?)make
und andere auf Zeitstempeln basierende Neukompilierungswerkzeuge lösen eine Neukompilierung des Clients aus, wenn sie ' wieder geändert (schlecht!)#define
ala #define S std::string("abc")
"einzugeben", aber die Konstante vermeidet die wiederholte Erstellung unterschiedlicher temporärer Werte an jedem Verwendungspunktconst
-Wert, der die Arbeit und die Auswirkung minimiert, wenn zwischen den beiden gewechselt wird#define X "x"
und einigen Client-Verwendungszwecken "pre" X "post"
X nicht nur durch Neukompilierung, sondern durch Erzwingen von Änderungen am Client-Code zu einer zur Laufzeit änderbaren Variablen gemacht werden soll oder muss. wohingegen dieser Übergang von einem const char*
oder const std::string
einfacher ist, da sie den Benutzer bereits zwingen, Verkettungsoperationen einzubeziehen (z. B. "pre" + X + "post"
für string
)sizeof
nicht direkt für ein definiertes numerisches Literal verwendenunsigned
){ 1, 2 }
, mit denen Arrays initialisiert werden können, oder #define MICROSECONDS *1E-6
usw. (definitiv dies wird nicht empfohlen!)__FILE__
und __LINE__
können in die Makrosubstitution einbezogen werden#if
Anweisungen auf Existenz und Wert testen, um Code bedingt einzuschließen (leistungsfähiger als eine Nachbearbeitung, wenn der Code nicht kompilierbar sein muss, wenn er nicht vom Präprozessor ausgewählt wurde). Verwenden Sie #undef
-ine, neu definieren usw.make
und andere auf Zeitstempeln basierende Neukompilierungs-Tools lösen eine Neukompilierung des Clients aus, wenn sie geändert werden (fehlerhaft!).Im Allgemeinen verwende ich const
s und betrachte sie als die professionellste Option für den allgemeinen Gebrauch (obwohl die anderen eine Einfachheit haben, die diesen alten faulen Programmierer anspricht).
Wenn dies eine C++ - Frage ist und als Alternative #define
erwähnt wird, handelt es sich um "globale" Konstanten (d. H. Dateibereich), nicht um Klassenmitglieder. Wenn es um solche Konstanten in C++ geht, ist static const
überflüssig. In C++ haben const
standardmäßig eine interne Verknüpfung und es ist sinnlos, sie als static
zu deklarieren. Es geht also wirklich um const
vs. #define
.
Und schließlich ist in C++ const
vorzuziehen. Zumindest deshalb, weil solche Konstanten typisiert und definiert sind. Es gibt einfach keine Gründe, #define
gegenüber const
vorzuziehen, abgesehen von wenigen Ausnahmen.
String-Konstanten (BTW) sind ein Beispiel für eine solche Ausnahme. Mit #define
d-String-Konstanten kann die Kompilierungsfunktion von C/C++ - Compilern wie in verwendet werden
#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. Nur für den Fall, dass jemand static const
als Alternative zu #define
erwähnt, bedeutet dies normalerweise, dass er über C und nicht über C++ spricht. Ich frage mich, ob diese Frage richtig markiert wurde ...
Die Verwendung einer statischen const-Anweisung ist vergleichbar mit den anderen const-Variablen in Ihrem Code. Dies bedeutet, dass Sie nachverfolgen können, woher die Informationen stammen, im Gegensatz zu einem #define-Element, das im Pre-Compilierungsprozess einfach im Code ersetzt wird.
Vielleicht möchten Sie einen Blick auf C++ FAQ Lite für diese Frage werfen: http://www.parashift.com/c++-faq-lite/newbie.html#faq-29.7
Normalerweise sollten Sie statische Konstanten bevorzugen. Es hat keinen Nachteil. Der Prozessor sollte hauptsächlich für die bedingte Kompilierung verwendet werden (und manchmal für wirklich schmutzige Trics).
Das Definieren von Konstanten mithilfe der Präprozessor-Direktive #define
wird nicht empfohlen, nicht nur in C++
, sondern auch in C
anzuwenden. Diese Konstanten haben nicht den Typ. Sogar in C
wurde vorgeschlagen, const
für Konstanten zu verwenden.
#define
kann zu unerwarteten Ergebnissen führen:
#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;
}
Gibt ein falsches Ergebnis aus:
y is 505
z is 510
Wenn Sie dies jedoch durch Konstanten ersetzen:
#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;
}
Es gibt das richtige Ergebnis aus:
y is 505
z is 1010
Dies liegt daran, dass #define
einfach den Text ersetzt. Da dies die Reihenfolge der Operationen ernsthaft durcheinander bringen kann, würde ich empfehlen, stattdessen eine konstante Variable zu verwenden.
Bitte sehen Sie hier: static const vs define
normalerweise ist eine const-Deklaration (beachten Sie, dass es nicht statisch sein muss) der richtige Weg
Bevorzugen Sie immer die Sprachfunktionen gegenüber einigen zusätzlichen Tools wie dem Präprozessor.
ES.31: Verwenden Sie keine Makros für Konstanten oder "Funktionen"
Makros sind eine Hauptursache für Fehler. Makros befolgen nicht den üblichen Bereich und geben Sie Regeln ein. Makros befolgen nicht die üblichen Regeln für Argument Vorbeigehen. Makros sorgen dafür, dass der menschliche Leser etwas anderes sieht von dem, was der Compiler sieht. Makros erschweren das Erstellen von Werkzeugen.
Wenn Sie eine Konstante definieren, die von allen Instanzen der Klasse gemeinsam genutzt werden soll, verwenden Sie statische const. Wenn die Konstante für jede Instanz spezifisch ist, verwenden Sie einfach const (beachten Sie jedoch, dass alle Konstruktoren der Klasse diese const-Membervariable in der Initialisierungsliste initialisieren müssen).