Gibt es einen Vorteil, konstante lokale Variablen als statisch (c ++) zu definieren?

9
void Animation::playAnimation() const
{
    static const int index = 0;
    const std::string& animationFileName = 
    m_animationContainer.getAnimationName(index);
    static const int zOrder = -1;
    static bool isLooping = false;

    AnimationBank::play(animationFileName,
                        zOrder,
                        isLooping);
}

Gibt es einen Vorteil, konstante lokale Variablen als zu definieren static? Oder es ist unnötig und sogar schlechte Praxis.

TM
quelle
2
... auch bitte nicht über Kreuz posten : stackoverflow.com/questions/44431574/… "Cross-Posting ist verpönt, da es zu fragmentierten Antworten führt, die im ganzen Netzwerk verteilt sind ..."
Mücke
Frage bearbeitet.
TM

Antworten:

10

Abgesehen von der sehr guten Antwort von @ Christophe ist der für die Statik generierte Code höchstwahrscheinlich schlechter als der für die lokale Variable. Wenn Sie also an dem Vorteil unter der Haube interessiert sind, ist die Statik auf modernen Prozessoren schlechter.

Der Grund ist, dass sich die Statik irgendwo im Speicher befinden muss, der von allen anderen Threads und von allen anderen Aufrufen gefunden werden kann. Dies bedeutet im Grunde, sie in den globalen Speicher zu stellen.

Im Laufe der Jahre haben Prozessoren und Compiler zusammen den Zugriff auf lokale Variablen aufgrund der Beliebtheit ihrer Verwendung im Vergleich zu anderen Variablen wie Globals, Statik und Feldern erheblich optimiert. Der Compiler kann sich dafür entscheiden, eine lokale Variable in einem CPU-Register zu speichern, und selbst wenn dies nicht der Fall ist (daher wird stattdessen der Aufrufstapel verwendet), befindet sich der gesamte Stapel mit ziemlicher Sicherheit im Cache. Der Zugriff auf den Stapel erfolgt normalerweise über einen Adressierungsmodus mit kurzer Verschiebung (außerhalb des Stapelzeigerregisters). Für den Zugriff auf Globals oder Statics ist jedoch normalerweise ein erweiterter Offset oder eine erweiterte absolute Adresse erforderlich, sodass die daraus resultierenden Anweisungen länger sind als die entsprechenden für den Stapelspeicherzugriff.

Alles in allem kann der Compiler aufgrund der Kombination von statisch und const erkennen, dass er den konstanten Wert am Verwendungsort ersetzen kann, sodass die Verwendung von const möglicherweise das oben Gesagte mildert. Ihr Snippet zeigt jedoch mindestens eine nicht konstante Statik an, sodass die Diskussion möglicherweise aktuell ist.

Erik Eidt
quelle
6
Sind Sie sicher, dass statische Konstanten gespeichert werden müssen?
MikeMB
5

Es geht nicht um Vorteile, sondern um Semantik:

  • Eine statische Variable in einer Funktion (sogar eine Mitgliedsfunktion) bedeutet, dass die Variable von allen Aufrufen dieser Funktion gemeinsam genutzt wird. Ein Aufruf dieser Funktion hat also einen Nebeneffekt auf die nachfolgenden Aufrufe.

  • Eine nicht statische Variable ist für jede Ausführung der Funktion eindeutig.

Halten Sie lokale Variablen nicht statisch, es sei denn, dies ist aus einem bestimmten und gut begründeten Grund erforderlich.

Zusätzliche Anmerkung: Die statische Variable wird auch von verschiedenen Threads gemeinsam genutzt. Das Aufrufen dieser Funktion von mehr als einem Thread gleichzeitig kann zu Race-Bedingungen und UB führen (selbst wenn sie für verschiedene Objekte aufgerufen werden).

Christophe
quelle
4
Ab C ++ 11 definiert der Standard konstante statische Variablen threadsicher. Nicht konstante statische Variablen hingegen nicht.
Teimpz
5
Hier geht es um Konstanten. Sie können ihren Wert nicht ändern, daher gibt es keinen bedeutenden semantischen Unterschied zwischen Konstanten, die von mehreren Funktionsaufrufen und lokalen gemeinsam genutzt werden.
MikeMB
Der einzige Unterschied besteht darin, ob die Initialisierung Nebenwirkungen hat.
MikeMB
1
@ MikeMB In der Tat war meine Antwort allgemein. Wenn dies constder Fall ist, wird es vom Optimierer trotzdem weitergegeben, unabhängig davon, ob dies der Fall ist staticoder nicht. Es gibt jedoch noch einen subtilen Unterschied: Wie Sie bereits betont haben, kann der Objektinitialisierer einige Nebenwirkungen haben, sodass die Auswahl von statisch oder nicht das erwartete Verhalten verzerren kann. Aus all diesen Gründen würde ich immer noch dringend empfehlen, staticgenau dann zu verwenden, wenn dies constwirklich etwas ist, das eng mit der Klasse verbunden ist. Zeigen Sie die Absicht im Code und lassen Sie das Optimierungsprogramm seine Arbeit erledigen.
Christophe
Semantisch macht es also keinen Unterschied, ob die Variable eine Konstante ist und ihre Adresse nicht verwendet wird. Der Rest der Frage lautet: Welches sollten Sie verwenden?
user253751
1

Bei jedem Aufruf der Funktion wird eine lokale Variable initialisiert oder erstellt. Lokale Variablen werden auf dem Stapel gespeichert und sind daher im Allgemeinen threadsicher.

Eine statische lokale Variable wird nur einmal initialisiert oder erstellt. Beim ersten Aufruf der Funktion. Lokale statische Variablen werden nicht auf dem Stapel gespeichert und sind daher im Allgemeinen nicht threadsicher.

Eine konstante lokale Variable ist eine Variable, die sich nicht ändert und bei jedem Aufruf der Funktion initialisiert oder erstellt wird. Lokale const-Variablen werden auf dem Stapel gespeichert und sind daher im Allgemeinen threadsicher.

Eine lokale statische const-Variable ist eine Variable, die sich nicht ändert und nur einmal initialisiert oder erstellt wird. Beim ersten Aufruf der Funktion. Lokale statische const-Variablen werden nicht auf dem Stapel gespeichert und sind daher im Allgemeinen nicht threadsicher.

Compiler können möglicherweise const-Variablen in eine Kompilierungszeitkonstante optimieren.

Compiler können möglicherweise nicht statische Variablen optimieren, indem sie sie nicht im Stapel, sondern in Registern aufbewahren.

Theron W Genaux
quelle
Warum sollten lokale static constVariablen nicht threadsicher sein? Ihr Wert ist konstant, auch wenn sich ihr Wert auf der Hep befindet.
Unified Modeling Sandwich
@unifiedmodelingsandwich: Was ist, wenn zwei Threads gleichzeitig die Funktion zum ersten Mal aufrufen? Dann würden beide Threads versuchen, diese static constVariable zu initialisieren .
Bart van Ingen Schenau
Nicht in C ++ 11 würden sie nicht. Die dynamische Initialisierung der funktionslokalen Statik ist threadsicher.
Sebastian Redl
@BartvanIngenSchenau Seit C ++ 11 ist die Initialisierung statischer lokaler Variablen threadsicher . Das A sagt immer noch zu Recht, dass es im Allgemeinen nicht threadsicher ist, aber es wäre genauer zu sagen, dass dies nur vor C ++ 11 der Fall ist.
Unified Modeling Sandwich
1
@unifiedmodelingsandwich: Danke für die Info. Ich stecke meistens in C ++ 03 fest :-(
Bart van Ingen Schenau