Scott Meyers behandelt dieses Thema sehr schön und gründlich. Sein Artikel Nr. 2 in "Effective C ++ Third Edition". Zwei Sonderfälle (1) Eine statische Konstante wird innerhalb eines Klassenbereichs für klassenspezifische Konstanten bevorzugt. (2) Namespace oder anonyme Bereichskonstante wird gegenüber #define bevorzugt.
Eric
2
Ich bevorzuge Enums. Weil es eine Mischung aus beidem ist. Nimmt keinen Platz ein, es sei denn, Sie erstellen eine Variable davon. Wenn Sie nur als Konstante verwenden möchten, ist enum die beste Option. Es hat Typensicherheit in C / C ++ 11 Standard und auch eine perfekte Konstante. #define ist vom Typ unsicher, const benötigt Speicherplatz, wenn der Compiler ihn nicht optimieren kann.
Siddhusingh
1
Meine Entscheidung, ob #defineoder static const(für Zeichenfolgen) verwendet werden soll, hängt vom Initialisierungsaspekt ab (der in den folgenden Antworten nicht erwähnt wurde): Wenn die Konstante nur innerhalb einer bestimmten Kompilierungseinheit verwendet wird, gehe ich mit static const, ansonsten verwende ich #define- vermeiden Sie das Fiasko der Initialisierung der statischen Reihenfolge isocpp.org/wiki/faq/ctors#static-init-order
Martin Dvorak
Wenn const, constexproder enumoder jegliche Variation Werke in Ihrem Fall bevorzugen sie dann#define
Phil1970
@MartinDvorak " Fiasko bei der Initialisierung statischer Ordnungen vermeiden " Wie ist das ein Problem für Konstanten?
neugieriger Kerl
Antworten:
139
Persönlich verabscheue ich den Präprozessor, also würde ich immer mitgehen const.
Der Hauptvorteil von a #definebesteht darin, dass zum Speichern in Ihrem Programm kein Speicher erforderlich ist, da nur Text durch einen Literalwert ersetzt wird. Es hat auch den Vorteil, dass es keinen Typ hat, so dass es für jeden ganzzahligen Wert verwendet werden kann, ohne Warnungen zu generieren.
Die Vorteile von " const" s bestehen darin, dass sie einen Gültigkeitsbereich haben und in Situationen verwendet werden können, in denen ein Zeiger auf ein Objekt übergeben werden muss.
Ich weiß allerdings nicht genau, was Sie mit dem " static" Teil anfangen. Wenn Sie global deklarieren, würde ich es in einen anonymen Namespace stellen, anstatt es zu verwenden static. Beispielsweise
namespace{unsignedconst seconds_per_minute =60;};int main (int argc;char*argv[]){...}
String- Konstanten sind speziell diejenigen, die von #defined profitieren könnten , zumindest wenn sie als "Bausteine" für größere String-Konstanten verwendet werden können. Siehe meine Antwort für ein Beispiel.
Am
62
Der #defineVorteil, keinen Speicher zu verwenden, ist ungenau. Die "60" im Beispiel muss irgendwo gespeichert werden, unabhängig davon, ob es sich um static constoder handelt #define. Tatsächlich habe ich Compiler gesehen, bei denen die Verwendung von #define einen massiven (schreibgeschützten) Speicherverbrauch verursachte und die statische Konstante keinen nicht benötigten Speicher verwendete.
Gilad Naor
3
Ein #define ist so, als hätten Sie es eingegeben, es kommt also definitiv nicht aus dem Speicher.
der Reverend
27
@theReverend Sind Literalwerte irgendwie vom Verbrauch von Maschinenressourcen befreit? Nein, sie verwenden sie möglicherweise auf unterschiedliche Weise. Möglicherweise wird sie nicht auf dem Stapel oder Heap angezeigt, aber irgendwann wird das Programm zusammen mit allen darin kompilierten Werten in den Speicher geladen.
Sqeaky
13
@ gilad-naor, Sie haben im Allgemeinen Recht, aber kleine ganze Zahlen wie 60 können tatsächlich manchmal eine Art Teilausnahme sein. Einige Befehlssätze können Ganzzahlen oder eine Teilmenge von Ganzzahlen direkt im Befehlsstrom codieren. Beispielsweise werden MIPs sofort hinzugefügt ( cs.umd.edu/class/sum2003/cmsc311/Notes/Mips/addi.html ). In einem solchen Fall kann man sagen, dass eine # definierte Ganzzahl wirklich keinen Platz belegt, da sie in der kompilierten Binärdatei einige freie Bits in Anweisungen belegt, die ohnehin existieren mussten.
Ahcox
241
Vor- und Nachteile zwischen #defines, consts und (was Sie vergessen haben) enums, je nach Verwendung:
enums:
nur für ganzzahlige Werte möglich
Probleme mit ordnungsgemäßem Gültigkeitsbereich / Identifizierungskonflikten werden gut behandelt, insbesondere in C ++ 11-Aufzählungsklassen, in denen die Aufzählungen für enum class Xdurch den Bereich eindeutig sindX::
stark typisiert, aber auf eine ausreichend große int-Größe mit oder ohne Vorzeichen, über die Sie in C ++ 03 keine Kontrolle haben (obwohl Sie ein Bitfeld angeben können, in das sie gepackt werden sollen, wenn die Aufzählung ein Mitglied von struct / ist class / union), während C ++ 11 standardmäßig verwendet wird, intaber vom Programmierer explizit festgelegt werden kann
Ich kann die Adresse nicht annehmen - es gibt keine, da die Aufzählungswerte an den Verwendungspunkten effektiv inline ersetzt werden
Stärkere Nutzungsbeschränkungen (z. B. Inkrementieren - template <typename T> void f(T t) { cout << ++t; }wird nicht kompiliert, obwohl Sie eine Aufzählung mit implizitem Konstruktor, Casting-Operator und benutzerdefinierten Operatoren in eine Klasse einschließen können).
Der Typ jeder Konstante stammt aus der einschließenden Aufzählung. template <typename T> void f(T)Erhalten Sie also eine eindeutige Instanziierung, wenn Sie denselben numerischen Wert aus verschiedenen Aufzählungen übergeben, die sich alle von jeder tatsächlichen f(int)Instanziierung unterscheiden. Der Objektcode jeder Funktion könnte identisch sein (ohne Berücksichtigung von Adressversätzen), 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.
Selbst mit typeof / decltype kann numeric_limits keinen nützlichen Einblick in die Menge der aussagekräftigen Werte und Kombinationen bieten (tatsächlich werden "legale" Kombinationen im Quellcode nicht einmal notiert, bedenken Sie enum { A = 1, B = 2 }- ist A|B"legal" aus einer Programmlogik Perspektive?)
Der Typname der Aufzählung kann an verschiedenen Stellen in RTTI, Compilermeldungen usw. erscheinen - möglicherweise nützlich, möglicherweise verschleiert
Sie können keine Aufzählung verwenden, ohne dass die Übersetzungseinheit den Wert tatsächlich sieht. Dies bedeutet, dass Aufzählungen in Bibliotheks-APIs die im Header angegebenen Werte benötigen. makeAndere auf Zeitstempeln basierende Neukompilierungswerkzeuge lösen eine Client-Neukompilierung aus, wenn sie geändert werden (fehlerhaft! )
consts:
Probleme mit dem richtigen Umfang / Identifizierungskonflikt werden gut behandelt
starker, einzelner, benutzerdefinierter Typ
Sie könnten versuchen, ein #defineala zu "tippen" #define S std::string("abc"), aber die Konstante vermeidet die wiederholte Konstruktion unterschiedlicher Provisorien an jedem Verwendungspunkt
Komplikationen mit einer Definitionsregel
kann Adressen annehmen, konstante Verweise darauf erstellen usw.
Am ähnlichsten einem Nichtwert const, der Arbeit und Auswirkungen beim Wechsel zwischen beiden minimiert
Der Wert kann in die Implementierungsdatei eingefügt werden, sodass eine lokalisierte Neukompilierung und nur Client-Links die Änderung übernehmen können
#defines:
"globaler" Bereich / anfälliger für widersprüchliche Verwendungen, die zu schwer zu lösenden Kompilierungsproblemen und unerwarteten Laufzeitergebnissen führen können, anstatt zu vernünftigen Fehlermeldungen; Dies zu mildern erfordert:
lange, obskure und / oder zentral koordinierte Bezeichner, und der Zugriff auf diese kann nicht davon profitieren, dass gebrauchte / aktuelle / von Koenig nachgeschlagene Namespaces, Namespace-Aliase usw. implizit abgeglichen werden.
Während die bewährte Methode für das Trumping ermöglicht, dass Bezeichner von Vorlagenparametern einstellige Großbuchstaben (möglicherweise gefolgt von einer Zahl) sind, ist die andere Verwendung von Bezeichnern ohne Kleinbuchstaben herkömmlicherweise für Präprozessordefinitionen reserviert und wird von diesen erwartet (außerhalb der Betriebssystem- und C / C ++ - Bibliothek) Überschriften). Dies ist wichtig, damit die Verwendung von Präprozessoren im Unternehmensmaßstab überschaubar bleibt. Es ist zu erwarten, dass Bibliotheken von Drittanbietern die Anforderungen erfüllen. Wenn Sie dies beobachten, bedeutet die Migration vorhandener Konstanten oder Aufzählungen zu / von Definitionen eine Änderung der Großschreibung und erfordert daher Änderungen am Client-Quellcode anstelle einer "einfachen" Neukompilierung. (Ich persönlich schreibe den ersten Buchstaben der Aufzählungen groß, aber keine Konstanten, daher würde ich auch von der Migration zwischen diesen beiden betroffen sein - vielleicht ist es an der Zeit, das zu überdenken.)
Weitere Operationen zur Kompilierungszeit möglich: Verkettung von Zeichenfolgenliteralen, Zeichenfolge (unter Berücksichtigung ihrer Größe), Verkettung in Bezeichner
Nachteil ist , dass gegeben #define X "x"und einige Client - Nutzung ala "pre" X "post", wenn Sie wollen oder müssen , um X eine Laufzeit veränderliche Variable anstatt eine Konstante Sie Änderungen erzwingen Client - Code ( und nicht nur neu kompiliert), während dieser Übergang leichter von einem ist const char*oder const std::stringsie gegeben den Benutzer bereits zwingen, Verkettungsoperationen einzubeziehen (z. B. "pre" + X + "post"für string)
kann nicht sizeofdirekt für ein definiertes numerisches Literal verwendet werden
untypisiert (GCC warnt nicht im Vergleich zu unsigned)
Einige Compiler- / Linker- / Debugger-Ketten enthalten möglicherweise keine Kennung, sodass Sie sich nur noch auf "magische Zahlen" (Zeichenfolgen, was auch immer ...) konzentrieren müssen.
kann die Adresse nicht nehmen
Der ersetzte Wert muss in dem Kontext, in dem #define erstellt wird, nicht legal (oder diskret) sein, da er an jedem Verwendungspunkt ausgewertet wird, sodass Sie auf noch nicht deklarierte Objekte verweisen können. Dies hängt von der "Implementierung" ab, die nicht benötigt wird vorab enthalten sein, "Konstanten" erstellen, wie { 1, 2 }sie zum Initialisieren von Arrays #define MICROSECONDS *1E-6usw. verwendet werden können (dies wird definitiv nicht empfohlen!)
Einige spezielle Dinge wie __FILE__und __LINE__können in die Makrosubstitution integriert werden
Sie können in #ifAnweisungen auf Existenz und Wert testen, um Code unter bestimmten Bedingungen einzuschließen (leistungsfähiger als eine Nachverarbeitung "if", da der Code nicht kompilierbar sein muss, wenn er nicht vom Präprozessor ausgewählt wurde), #undef-ine verwenden, neu definieren usw.
Ersetzter Text muss verfügbar gemacht werden:
in der Übersetzungseinheit, von der es verwendet wird, was bedeutet, dass sich Makros in Bibliotheken für die Client-Verwendung im Header befinden müssen, sodass makeandere auf Zeitstempeln basierende Neukompilierungswerkzeuge die Neukompilierung des Clients auslösen, wenn sie geändert werden (schlecht!)
oder in der Befehlszeile, wo noch mehr Sorgfalt erforderlich ist, um sicherzustellen, dass der Clientcode neu kompiliert wird (z. B. sollte das Makefile oder Skript, das die Definition liefert, als Abhängigkeit aufgeführt werden).
Meine persönliche Meinung:
In der Regel verwende ich consts und betrachte sie als die professionellste Option für den allgemeinen Gebrauch (obwohl die anderen eine Einfachheit haben, die diesen alten faulen Programmierer anspricht).
Tolle Antwort. Ein kleiner Fehler: Ich verwende manchmal lokale Aufzählungen, die sich überhaupt nicht in Headern befinden, nur um den Code klarer zu machen, wie bei kleinen Zustandsautomaten und dergleichen. Sie müssen also nicht immer in Kopfzeilen stehen.
kert
Die Vor- und Nachteile sind verwechselt, ich würde sehr gerne eine Vergleichstabelle sehen.
Unbekannt123
@ Unknown123: zögern Sie nicht, einen zu posten - es macht mir nichts aus, wenn Sie Punkte abreißen, die Sie von hier aus für würdig halten. Prost
Tony Delroy
48
Wenn es sich um eine C ++ - Frage handelt, die #defineals Alternative erwähnt wird, handelt es sich um "globale" Konstanten (dh Dateibereichskonstanten), nicht um Klassenmitglieder. Wenn es um solche Konstanten in C ++ geht, static constist dies redundant. In C ++ constsind standardmäßig interne Verknüpfungen vorhanden, und es macht keinen Sinn, diese zu deklarieren static. So ist es wirklich über constvs. #define.
Und schließlich ist in C ++ constvorzuziehen. Zumindest, weil solche Konstanten typisiert und mit Gültigkeitsbereich versehen sind. Es gibt einfach keinen Grund zu bevorzugen #defineüber const, abgesehen von wenigen Ausnahmen.
String-Konstanten, BTW, sind ein Beispiel für eine solche Ausnahme. Mit #defined String-Konstanten kann die Verkettungsfunktion zur Kompilierungszeit von C / C ++ - Compilern wie in verwendet werden
PS Noch einmal, nur für den Fall, dass jemand static constals Alternative zu erwähnt #define, bedeutet dies normalerweise, dass er über C spricht, nicht über C ++. Ich frage mich, ob diese Frage richtig markiert ist ...
" einfach keine Gründe, #define vorzuziehen " gegenüber was? In einer Header-Datei definierte statische Variablen?
Neugieriger
9
#define kann zu unerwarteten Ergebnissen führen:
#include<iostream>#define x 500#define y x +5int z = y *2;int main(){
std::cout <<"y is "<< y;
std::cout <<"\nz is "<< z;}
Gibt ein falsches Ergebnis aus:
y is505
z is510
Wenn Sie dies jedoch durch Konstanten ersetzen:
#include<iostream>constint x =500;constint 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 is505
z is1010
Dies liegt daran, dass #defineder Text einfach ersetzt wird. Da dies die Reihenfolge der Operationen ernsthaft beeinträchtigen kann, würde ich empfehlen, stattdessen eine konstante Variable zu verwenden.
Ich hatte ein anderes unerwartetes Ergebnis: yhatte den Wert 5500, eine Little-Endian-Verkettung von xund 5.
Codes mit Hammer
5
Die Verwendung einer statischen Konstante entspricht der Verwendung anderer Konstantenvariablen in Ihrem Code. Dies bedeutet, dass Sie verfolgen können, woher die Informationen stammen, im Gegensatz zu einem #define, das im Vorkompilierungsprozess einfach im Code ersetzt wird.
Eine statische Konstante wird eingegeben (sie hat einen Typ) und kann vom Compiler auf Gültigkeit, Neudefinition usw. überprüft werden.
Ein #define kann undefiniert neu definiert werden.
Normalerweise sollten Sie statische Konstanten bevorzugen. Es hat keinen Nachteil. Der Prozessor sollte hauptsächlich für die bedingte Kompilierung verwendet werden (und manchmal auch für wirklich schmutzige Trics).
Das Definieren von Konstanten mithilfe der Präprozessor-Direktive #definewird nicht empfohlen, nicht nur in C++, sondern auch in anzuwenden C. Diese Konstanten haben nicht den Typ. Auch in Cwurde vorgeschlagen, constfür Konstanten zu verwenden.
Ziehen Sie es immer vor, die Sprachfunktionen gegenüber einigen zusätzlichen Tools wie dem Präprozessor zu verwenden.
ES.31: Verwenden Sie keine Makros für Konstanten oder "Funktionen"
Makros sind eine Hauptquelle für Fehler. Makros halten sich nicht an die üblichen Regeln für Umfang und Typ. Makros befolgen nicht die üblichen Regeln für die Übergabe von Argumenten. Makros stellen sicher, dass der menschliche Leser etwas anderes sieht als der Compiler. Makros erschweren die Werkzeugerstellung.
Wenn Sie eine Konstante definieren, die von allen Instanzen der Klasse gemeinsam genutzt werden soll, verwenden Sie die statische Konstante. Wenn die Konstante für jede Instanz spezifisch ist, verwenden Sie einfach const (beachten Sie jedoch, dass alle Konstruktoren der Klasse diese const-Mitgliedsvariable in der Initialisierungsliste initialisieren müssen).
#define
oderstatic const
(für Zeichenfolgen) verwendet werden soll, hängt vom Initialisierungsaspekt ab (der in den folgenden Antworten nicht erwähnt wurde): Wenn die Konstante nur innerhalb einer bestimmten Kompilierungseinheit verwendet wird, gehe ich mitstatic const
, ansonsten verwende ich#define
- vermeiden Sie das Fiasko der Initialisierung der statischen Reihenfolge isocpp.org/wiki/faq/ctors#static-init-orderconst
,constexpr
oderenum
oder jegliche Variation Werke in Ihrem Fall bevorzugen sie dann#define
Antworten:
Persönlich verabscheue ich den Präprozessor, also würde ich immer mitgehen
const
.Der Hauptvorteil von a
#define
besteht darin, dass zum Speichern in Ihrem Programm kein Speicher erforderlich ist, da nur Text durch einen Literalwert ersetzt wird. Es hat auch den Vorteil, dass es keinen Typ hat, so dass es für jeden ganzzahligen Wert verwendet werden kann, ohne Warnungen zu generieren.Die Vorteile von "
const
" s bestehen darin, dass sie einen Gültigkeitsbereich haben und in Situationen verwendet werden können, in denen ein Zeiger auf ein Objekt übergeben werden muss.Ich weiß allerdings nicht genau, was Sie mit dem "
static
" Teil anfangen. Wenn Sie global deklarieren, würde ich es in einen anonymen Namespace stellen, anstatt es zu verwendenstatic
. Beispielsweisequelle
#define
d profitieren könnten , zumindest wenn sie als "Bausteine" für größere String-Konstanten verwendet werden können. Siehe meine Antwort für ein Beispiel.#define
Vorteil, keinen Speicher zu verwenden, ist ungenau. Die "60" im Beispiel muss irgendwo gespeichert werden, unabhängig davon, ob es sich umstatic const
oder handelt#define
. Tatsächlich habe ich Compiler gesehen, bei denen die Verwendung von #define einen massiven (schreibgeschützten) Speicherverbrauch verursachte und die statische Konstante keinen nicht benötigten Speicher verwendete.Vor- und Nachteile zwischen
#define
s,const
s und (was Sie vergessen haben)enum
s, je nach Verwendung:enum
s:enum class X
durch den Bereich eindeutig sindX::
int
aber vom Programmierer explizit festgelegt werden kanntemplate <typename T> void f(T t) { cout << ++t; }
wird nicht kompiliert, obwohl Sie eine Aufzählung mit implizitem Konstruktor, Casting-Operator und benutzerdefinierten Operatoren in eine Klasse einschließen können).template <typename T> void f(T)
Erhalten Sie also eine eindeutige Instanziierung, wenn Sie denselben numerischen Wert aus verschiedenen Aufzählungen übergeben, die sich alle von jeder tatsächlichenf(int)
Instanziierung unterscheiden. Der Objektcode jeder Funktion könnte identisch sein (ohne Berücksichtigung von Adressversätzen), 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 }
- istA|B
"legal" aus einer Programmlogik Perspektive?)make
Andere auf Zeitstempeln basierende Neukompilierungswerkzeuge lösen eine Client-Neukompilierung aus, wenn sie geändert werden (fehlerhaft! )const
s:#define
ala zu "tippen"#define S std::string("abc")
, aber die Konstante vermeidet die wiederholte Konstruktion unterschiedlicher Provisorien an jedem Verwendungspunktconst
, der Arbeit und Auswirkungen beim Wechsel zwischen beiden minimiert#define
s:#define X "x"
und einige Client - Nutzung ala"pre" X "post"
, wenn Sie wollen oder müssen , um X eine Laufzeit veränderliche Variable anstatt eine Konstante Sie Änderungen erzwingen Client - Code ( und nicht nur neu kompiliert), während dieser Übergang leichter von einem istconst char*
oderconst std::string
sie gegeben den Benutzer bereits zwingen, Verkettungsoperationen einzubeziehen (z. B."pre" + X + "post"
fürstring
)sizeof
direkt für ein definiertes numerisches Literal verwendet werdenunsigned
){ 1, 2 }
sie zum Initialisieren von Arrays#define MICROSECONDS *1E-6
usw. verwendet werden können (dies wird definitiv nicht empfohlen!)__FILE__
und__LINE__
können in die Makrosubstitution integriert werden#if
Anweisungen auf Existenz und Wert testen, um Code unter bestimmten Bedingungen einzuschließen (leistungsfähiger als eine Nachverarbeitung "if", da der Code nicht kompilierbar sein muss, wenn er nicht vom Präprozessor ausgewählt wurde),#undef
-ine verwenden, neu definieren usw.make
andere auf Zeitstempeln basierende Neukompilierungswerkzeuge die Neukompilierung des Clients auslösen, wenn sie geändert werden (schlecht!)Meine persönliche Meinung:
In der Regel 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).quelle
Wenn es sich um eine C ++ - Frage handelt, die
#define
als Alternative erwähnt wird, handelt es sich um "globale" Konstanten (dh Dateibereichskonstanten), nicht um Klassenmitglieder. Wenn es um solche Konstanten in C ++ geht,static const
ist dies redundant. In C ++const
sind standardmäßig interne Verknüpfungen vorhanden, und es macht keinen Sinn, diese zu deklarierenstatic
. So ist es wirklich überconst
vs.#define
.Und schließlich ist in C ++
const
vorzuziehen. Zumindest, weil solche Konstanten typisiert und mit Gültigkeitsbereich versehen sind. Es gibt einfach keinen Grund zu bevorzugen#define
überconst
, abgesehen von wenigen Ausnahmen.String-Konstanten, BTW, sind ein Beispiel für eine solche Ausnahme. Mit
#define
d String-Konstanten kann die Verkettungsfunktion zur Kompilierungszeit von C / C ++ - Compilern wie in verwendet werdenPS Noch einmal, nur für den Fall, dass jemand
static const
als Alternative zu erwähnt#define
, bedeutet dies normalerweise, dass er über C spricht, nicht über C ++. Ich frage mich, ob diese Frage richtig markiert ist ...quelle
#define
kann zu unerwarteten Ergebnissen führen:Gibt ein falsches Ergebnis aus:
Wenn Sie dies jedoch durch Konstanten ersetzen:
Es gibt das richtige Ergebnis aus:
Dies liegt daran, dass
#define
der Text einfach ersetzt wird. Da dies die Reihenfolge der Operationen ernsthaft beeinträchtigen kann, würde ich empfehlen, stattdessen eine konstante Variable zu verwenden.quelle
y
hatte den Wert5500
, eine Little-Endian-Verkettung vonx
und 5.Die Verwendung einer statischen Konstante entspricht der Verwendung anderer Konstantenvariablen in Ihrem Code. Dies bedeutet, dass Sie verfolgen können, woher die Informationen stammen, im Gegensatz zu einem #define, das im Vorkompilierungsprozess einfach im Code ersetzt wird.
Vielleicht möchten Sie sich die C ++ FAQ Lite für diese Frage ansehen: http://www.parashift.com/c++-faq-lite/newbie.html#faq-29.7
quelle
Normalerweise sollten Sie statische Konstanten bevorzugen. Es hat keinen Nachteil. Der Prozessor sollte hauptsächlich für die bedingte Kompilierung verwendet werden (und manchmal auch für wirklich schmutzige Trics).
quelle
Das Definieren von Konstanten mithilfe der Präprozessor-Direktive
#define
wird nicht empfohlen, nicht nur inC++
, sondern auch in anzuwendenC
. Diese Konstanten haben nicht den Typ. Auch inC
wurde vorgeschlagen,const
für Konstanten zu verwenden.quelle
Bitte sehen Sie hier: static const vs define
Normalerweise ist eine const-Deklaration (beachten Sie, dass sie nicht statisch sein muss) der richtige Weg
quelle
Ziehen Sie es immer vor, die Sprachfunktionen gegenüber einigen zusätzlichen Tools wie dem Präprozessor zu verwenden.
Aus den C ++ - Kernrichtlinien
quelle
Wenn Sie eine Konstante definieren, die von allen Instanzen der Klasse gemeinsam genutzt werden soll, verwenden Sie die statische Konstante. Wenn die Konstante für jede Instanz spezifisch ist, verwenden Sie einfach const (beachten Sie jedoch, dass alle Konstruktoren der Klasse diese const-Mitgliedsvariable in der Initialisierungsliste initialisieren müssen).
quelle