Ich denke, dir fehlt hier etwas.
statische Funktion?
Wenn Sie eine Funktion als statisch deklarieren, wird sie in ihrer Kompilierungseinheit "versteckt".
Ein Name mit Namespace-Bereich (3.3.6) hat eine interne Verknüpfung, wenn es sich um den Namen von handelt
- eine Variable, Funktion oder Funktionsvorlage, die explizit als statisch deklariert ist;
3,5 / 3 - C ++ 14 (n3797)
Wenn ein Name eine interne Verknüpfung hat, kann auf die Entität, die er bezeichnet, durch Namen aus anderen Bereichen in derselben Übersetzungseinheit verwiesen werden.
3,5 / 2 - C ++ 14 (n3797)
Wenn Sie diese statische Funktion in einem Header deklarieren, verfügen alle Kompilierungseinheiten einschließlich dieses Headers über eine eigene Kopie der Funktion.
Die Sache ist, wenn diese Funktion statische Variablen enthält, hat jede Kompilierungseinheit, die diesen Header enthält, auch eine eigene, persönliche Version.
Inline-Funktion?
Wenn Sie es als Inline deklarieren, ist es ein Kandidat für Inlining (dies bedeutet heutzutage in C ++ nicht viel, da der Compiler inline ist oder nicht, wobei manchmal die Tatsache ignoriert wird, dass das Schlüsselwort inline vorhanden ist oder fehlt):
Eine Funktionsdeklaration (8.3.5, 9.3, 11.3) mit einem Inline-Spezifizierer deklariert eine Inline-Funktion. Der Inline-Spezifizierer gibt der Implementierung an, dass die Inline-Substitution des Funktionskörpers am Aufrufpunkt dem üblichen Funktionsaufrufmechanismus vorzuziehen ist. Eine Implementierung ist nicht erforderlich, um diese Inline-Ersetzung am Aufrufpunkt durchzuführen. Selbst wenn diese Inline-Ersetzung weggelassen wird, bleiben die anderen in 7.1.2 definierten Regeln für Inline-Funktionen ein.
7.1.2 / 2 - C ++ 14 (n3797)
In einem Header hat dies einen interessanten Nebeneffekt: Die Inlined-Funktion kann im selben Modul mehrmals definiert werden, und der Linker fügt "sie" einfach zu einem zusammen (wenn sie aus Compiler-Gründen nicht inliniert wurden).
Für statische Variablen, die im Inneren deklariert sind, gibt der Standard ausdrücklich eine und nur eine davon an:
Eine statische lokale Variable in einer externen Inline-Funktion bezieht sich immer auf dasselbe Objekt.
7.1.2 / 4 - C ++ 98 / C ++ 14 (n3797)
(Funktionen sind standardmäßig extern. Wenn Sie Ihre Funktion nicht ausdrücklich als statisch markieren, gilt dies für diese Funktion.)
Dies hat den Vorteil "statisch" (dh es kann in einem Header definiert werden) ohne seine Fehler (es existiert höchstens einmal, wenn es nicht inline ist)
statische lokale Variable?
Statische lokale Variablen haben keine Verknüpfung (sie können außerhalb ihres Gültigkeitsbereichs nicht mit Namen bezeichnet werden), haben jedoch eine statische Speicherdauer (dh sie sind global, aber ihre Konstruktion und Zerstörung unterliegen bestimmten Regeln).
statisch + inline?
Das Mischen von Inline und Static hat dann die von Ihnen beschriebenen Konsequenzen (selbst wenn die Funktion inline ist, ist die darin enthaltene statische Variable nicht vorhanden, und Sie werden mit so vielen statischen Variablen enden, wie Sie über Kompilierungseinheiten verfügen, einschließlich der Definition Ihrer statischen Funktionen ).
Antwort auf die zusätzliche Frage des Autors
Seit ich die Frage geschrieben habe, habe ich sie mit Visual Studio 2008 ausprobiert. Ich habe versucht, alle Optionen zu aktivieren, mit denen VS in Übereinstimmung mit Standards funktioniert, aber es ist möglich, dass ich einige verpasst habe. Dies sind die Ergebnisse:
Wenn die Funktion nur "inline" ist, gibt es nur eine Kopie der statischen Variablen.
Wenn die Funktion "statisch inline" ist, gibt es so viele Kopien wie Übersetzungseinheiten.
Die eigentliche Frage ist nun, ob die Dinge so sein sollen oder ob dies eine Eigenart des Microsoft C ++ - Compilers ist.
Ich nehme an, Sie haben so etwas:
void doSomething()
{
static int value ;
}
Sie müssen sich darüber im Klaren sein, dass die statische Variable innerhalb der Funktion, einfach ausgedrückt, eine globale Variable ist, die für alle außer dem Funktionsumfang verborgen ist, was bedeutet, dass nur die Funktion, in der sie deklariert ist, sie erreichen kann.
Das Inlining der Funktion ändert nichts:
inline void doSomething()
{
static int value ;
}
Es wird nur eine versteckte globale Variable geben. Die Tatsache, dass der Compiler versucht, den Code einzubinden, ändert nichts an der Tatsache, dass es nur eine globale versteckte Variable gibt.
Wenn Ihre Funktion nun als statisch deklariert ist:
static void doSomething()
{
static int value ;
}
Dann ist es für jede Kompilierungseinheit "privat", was bedeutet, dass jede CPP-Datei einschließlich des Headers, in dem die statische Funktion deklariert ist, eine eigene private Kopie der Funktion hat, einschließlich ihrer eigenen privaten Kopie der globalen versteckten Variablen, also so viele Variablen wie Es gibt Kompilierungseinheiten einschließlich des Headers.
Hinzufügen von "Inline" zu einer "statischen" Funktion mit einer "statischen" Variablen im Inneren:
inline static void doSomething()
{
static int value ;
}
hat das gleiche Ergebnis, als dieses "Inline" -Schlüsselwort nicht hinzuzufügen, was die darin enthaltene statische Variable betrifft.
Das Verhalten von VC ++ ist also korrekt, und Sie verwechseln die wahre Bedeutung von "Inline" und "Static".
inline void doSomething() { static int value ; }
, die Funktion hat externe Verknüpfung; Dies ist eine ODR-Verletzung, wenn sie in einem Header angezeigt wird, der aus zwei verschiedenen Einheiten stammtinline
, es kann nicht ODR verletzen.Ich glaube, der Compiler erstellt viele Kopien der Variablen, aber der Linker wählt eine aus und lässt alle anderen darauf verweisen. Ich hatte ähnliche Ergebnisse, als ich ein Experiment versuchte, um verschiedene Versionen einer Inline-Funktion zu erstellen. Wenn die Funktion nicht tatsächlich inline war (Debug-Modus), gingen alle Aufrufe an dieselbe Funktion, unabhängig von der Quelldatei, aus der sie aufgerufen wurden.
Denken Sie einen Moment wie ein Compiler - wie könnte es anders sein? Jede Kompilierungseinheit (Quelldatei) ist unabhängig von den anderen und kann separat kompiliert werden. Jeder muss daher eine Kopie der Variablen erstellen, da er denkt, dass dies die einzige ist. Der Linker kann diese Grenzen überschreiten und die Referenzen sowohl für Variablen als auch für Funktionen anpassen.
quelle
Ich fand die Antwort von Mark Ransom hilfreich - dass der Compiler viele Kopien der statischen Variablen erstellt, der Linker jedoch eine auswählt und sie für alle Übersetzungseinheiten erzwingt.
An anderer Stelle fand ich Folgendes:
Siehe [dcl.fct.spec] / 4
Ich habe keine Kopie des Standards zu überprüfen, aber sie stimmt mit meiner Erfahrung bei der Prüfung der Baugruppe in VS Express 2008 überein
quelle
Es soll so sein. "static" teilt dem Compiler mit, dass die Funktion lokal für die Kompilierungseinheit sein soll. Daher möchten Sie eine Kopie pro Kompilierungseinheit und eine Kopie der statischen Variablen pro Instanz der Funktion.
"inline" wird verwendet, um dem Compiler mitzuteilen, dass die Funktion inline sein soll. Heutzutage wird nur angenommen, dass "es in Ordnung ist, wenn mehrere Kopien des Codes vorhanden sind, stellen Sie einfach sicher, dass es sich um dieselbe Funktion handelt". Jeder teilt also die statischen Variablen.
Hinweis: Diese Antwort wurde als Antwort auf die Antwort geschrieben, die das Originalplakat an sich selbst gesendet hat.
quelle
inline
bewirkt, dass die Funktion inline ist oder es in Ordnung ist, mehrere Kopien zu haben?inline
jedoch kein Inlining, sondern schlagen es nur vor und ermöglichen mehr als eine Definition (jedoch nicht in derselben Kompilierungseinheit).Seit ich die Frage geschrieben habe, habe ich sie mit Visual Studio 2008 ausprobiert. Ich habe versucht, alle Optionen zu aktivieren, mit denen VS in Übereinstimmung mit Standards funktioniert, aber es ist möglich, dass ich einige verpasst habe. Dies sind die Ergebnisse:
Wenn die Funktion nur "inline" ist, gibt es nur eine Kopie der statischen Variablen.
Wenn die Funktion "statisch inline" ist, gibt es so viele Kopien wie Übersetzungseinheiten.
Die eigentliche Frage ist nun, ob die Dinge so sein sollen oder ob dies eine Ideosynkratie des Microsoft C ++ - Compilers ist.
quelle
Inlining bedeutet, dass ausführbarer Code (Anweisungen) in den Code der aufrufenden Funktion eingefügt wird. Der Compiler kann dies unabhängig davon tun, ob Sie darum gebeten haben. Dies hat keine Auswirkungen auf die in der Funktion deklarierten Variablen (Daten).
quelle
Abgesehen von Designproblemen kann dies alles bedeuten, da Sie bereits daran festhalten, sollten Sie in diesem Fall statisch und nicht inline verwenden. Auf diese Weise teilen alle die gleichen Variablen. (Statische Funktion)
quelle
Ich glaube, Sie werden am Ende eine pro Übersetzungseinheit haben. Sie haben effektiv viele Versionen dieser Funktion (und ihrer deklarierten statischen Variablen), eine für jede Übersetzungseinheit, die den Header enthält.
quelle
Statisch bedeutet, dass eine Kopie im gesamten Programm verteilt ist. Inline bedeutet jedoch, dass derselbe Code mehrere Male im selben Programm benötigt wird, sodass es nicht möglich ist, eine Variable innerhalb der Inline-Funktion statisch zu machen.
quelle