Die kurze Antwort lautet: Es ist nicht nur static
nützlich, es wird auch immer erwünscht sein.
Beachten Sie zunächst, dass static
und constexpr
völlig unabhängig voneinander sind. static
definiert die Lebensdauer des Objekts während der Ausführung; constexpr
Gibt an, dass das Objekt während der Kompilierung verfügbar sein soll. Kompilierung und Ausführung sind zeitlich und räumlich unzusammenhängend und nicht zusammenhängend. Sobald das Programm kompiliert ist, constexpr
ist es nicht mehr relevant.
Jede Variable deklariert constexpr
ist implizit const
aber const
und static
sind fast orthogonal ( mit Ausnahme der Interaktion mit static const
ganzen Zahlen.)
Das C++
Objektmodell (§1.9) erfordert, dass alle Objekte außer Bitfeldern mindestens ein Byte Speicher belegen und Adressen haben; Darüber hinaus müssen alle in einem Programm zu einem bestimmten Zeitpunkt beobachtbaren Objekte unterschiedliche Adressen haben (Absatz 6). Dies erfordert nicht ganz, dass der Compiler für jeden Aufruf einer Funktion mit einem lokalen nicht statischen const-Array ein neues Array auf dem Stapel erstellt, da der Compiler in das as-if
Prinzip flüchten könnte, vorausgesetzt, er kann beweisen, dass kein anderes solches Objekt sein kann beobachtete.
Dies wird leider nicht leicht zu beweisen sein, es sei denn, die Funktion ist trivial (z. B. ruft sie keine andere Funktion auf, deren Körper in der Übersetzungseinheit nicht sichtbar ist), da Arrays mehr oder weniger per Definition Adressen sind. In den meisten Fällen muss das nicht statische const(expr)
Array bei jedem Aufruf auf dem Stapel neu erstellt werden, was den Punkt zunichte macht, dass es zur Kompilierungszeit berechnet werden kann.
Andererseits wird ein lokales static const
Objekt von allen Beobachtern gemeinsam genutzt und kann darüber hinaus initialisiert werden, selbst wenn die Funktion, in der es definiert ist, niemals aufgerufen wird. Keiner der oben genannten Punkte trifft also zu, und ein Compiler kann nicht nur eine einzige Instanz davon generieren. Es ist kostenlos, eine einzelne Instanz davon im Nur-Lese-Speicher zu generieren.
Sie sollten es also unbedingt static constexpr
in Ihrem Beispiel verwenden.
Es gibt jedoch einen Fall, in dem Sie nicht verwenden möchten static constexpr
. Sofern ein constexpr
deklariertes Objekt nicht ODR-verwendet oder deklariert ist static
, kann der Compiler es überhaupt nicht einschließen. Das ist ziemlich nützlich, da temporäre constexpr
Arrays zur Kompilierungszeit verwendet werden können, ohne das kompilierte Programm mit unnötigen Bytes zu belasten. In diesem Fall möchten Sie eindeutig nicht verwenden static
, da static
das Objekt wahrscheinlich zur Laufzeit erzwungen wird.
const
von einemconst
Objekt wegwerfen, nur von einem,const X*
das auf ein zeigtX
. Aber darum geht es nicht; Der Punkt ist, dass automatische Objekte keine statischen Adressen haben können. Wie gesagt,constexpr
hört nach Abschluss der Kompilierung auf, aussagekräftig zu sein, sodass nichts wegzuwerfen ist (und möglicherweise gar nichts, da nicht einmal garantiert wird, dass das Objekt zur Laufzeit existiert.)static
undconstexpr
erklären, dass sie orthogonal und unabhängig sind und verschiedene Dinge tun. Sie erwähnen dann einen Grund, die beiden NICHT zu kombinieren, da dies die ODR-Verwendung ignorieren würde (was nützlich erscheint). Oh und ich verstehe immer noch nicht, warum statisch mit constexpr verwendet werden sollte, da statisch für Laufzeitsachen ist. Sie haben nie erklärt, warum statisch mit constexpr wichtig ist.static constexpr
(es verhindert, dass das konstante Array bei jedem Funktionsaufruf neu erstellt werden muss), aber ich habe einige Wörter optimiert, die es klarer machen könnten. Vielen Dank.constexpr
konstante Variable nur in Kontexten zur Kompilierungszeit verwendet wird und zur Laufzeit nie benötigt wird,static
macht dies keinen Sinn, da der Wert zum Zeitpunkt der Laufzeit effektiv "inline" ist. Wennconstexpr
es jedoch in Laufzeitkontexten verwendet wird (mit anderen Worten, dasconstexpr
müssteconst
implizit konvertiert werden und mit einer physischen Adresse für Laufzeitcode verfügbar sein), möchtestatic
es die ODR-Konformität usw. sicherstellen. Das ist zumindest mein Verständnis.static constexpr int foo = 100;
. Es gibt keinen Grund, warum der Compiler die Verwendung vonfoo
überall nicht durch Literal ersetzen könnte100
, es sei denn, Code würde so etwas tun&foo
. Daher iststatic
onfoo
in diesem Fall nicht nützlich, dafoo
es zur Laufzeit nicht vorhanden ist. Wieder alles bis zum Compiler.Zusätzlich zur gegebenen Antwort ist zu beachten, dass der Compiler die
constexpr
Variable zum Zeitpunkt der Kompilierung nicht initialisieren muss , da Sie wissen, dass der Unterschied zwischenconstexpr
und darinstatic constexpr
besteht, dassstatic constexpr
Sie sicherstellen, dass die Variable nur einmal initialisiert wird.Der folgende Code zeigt, wie eine
constexpr
Variable mehrmals initialisiert wird (allerdings mit demselben Wert), während siestatic constexpr
sicherlich nur einmal initialisiert wird.Zusätzlich vergleicht der Code den Vorteil von
constexpr
gegenconst
in Kombination mitstatic
.Mögliche Programmausgabe:
Wie Sie sehen,
constexpr
wird Sie mehrfachstatic
initialisiert (Adresse ist nicht dieselbe), während das Schlüsselwort sicherstellt, dass die Initialisierung nur einmal durchgeführt wird.quelle
constexpr const short constexpr_short
um Fehler zu geben, wenn constexpr_short erneut initialisiert wirdconstexpr const
macht keinen Sinn , weilconstexpr
schon istconst
, das Hinzufügenconst
einmal oder mehrmals durch Compiler ignoriert. Sie versuchen, einen Fehler abzufangen, aber dies ist kein Fehler. So funktionieren die meisten Compiler.