const-Variablen in der header-Datei und die statische Initialisierung Fiasko
Nach der Lektüre eine Menge der Fragen bezüglich der Initialisierung von statischen Variablen bin ich noch nicht sicher, wie dies gilt für const
Variablen auf namespace-Ebene.
Ich habe diese Art von den folgenden code in eine header Datei config.h
erzeugt durch das build-Skript:
static const std::string path1 = "/xyz/abc";
static const std::string path2 = "/etc";
Je nach dem was ich gelesen habe, die static
Stichwort ist nicht notwendig, sogar veraltet hier.
Meine Frage: Ist der obige code anfällig für die statische Initialisierung Fiasko?
Wenn ich das folgende in einem header Datei myclass.h
:
class MyClass
{
public:
MyClass(const std::string& str) : m_str(str) {}
std::string Get() const { return m_str; }
private:
std::string m_str;
}
const MyClass myclass1("test");
Wird diese pose auch keine Probleme mit statischer Initialisierung?
Wenn ich das richtig verstanden, aufgrund const
Variablen auf, die interne Verlinkung sollte es kein problem sein, in beiden Fällen?
Edit: (aufgrund dribeas Antwort)
Vielleicht sollte ich erwähnen, dass ich mich für Anwendungsfälle wie:
In main.cpp
:
#include <config.h>
#include <myclass.h>
std::string anotherString(path1 + myclass1.Get());
int main()
{
...
}
Andere Frage bezüglich dieser use-case: Wird die compiler-Optimierung entfernt path2
in diesem Fall?
InformationsquelleAutor Hanno S. | 2011-01-26
Du musst angemeldet sein, um einen Kommentar abzugeben.
Ihre erste definition Orte
path1
in jeder compilation unit enthältconfig.h
. Um dies zu vermeiden, nicht bei der Definition von Variablen in header-Dateien. In der Regel würden Sie deklarieren Sie die Variablen in der Kopfzeile alsextern
:definieren und diese in einer übersetzung Einheit, z.B.
config.cpp
:Manchmal müssen Sie eine Konstante variable, die kann nur von einem übersetzungs-Einheit. Dann können Sie erklären, dass Variablen auf file-scope als
static
.static
ist nicht veraltet, nicht mehr.static
undextern
sind manchmal angedeutet, aber ich vergesse immer, wo und wie, damit ich in der Regel geben Sie diese explizit für alle namespace-level-Variablen.static
kann nur verwendet werden, in der Umsetzung Dateien.natürlich, es ist kein Konzept für die Umsetzung-Datei in C++ an alle, ich werde versuchen, die Worte zu verändern
Ich denke, die phrase, die Sie suchen, ist "translation unit" statt Umsetzung-Datei. Werte sollten deklariert werden, der im Header definiert und in höchstens einer übersetzungseinheit. In diesem Fall, da Sie sind const und implizite interne Verlinkung, die Sie nicht bekommen, eine mehrfach definierte symbol Fehler beim link-Zeit, aber Sie haben die gleiche definierte symbol in jeder übersetzungseinheit enthält dieser header. Da Sie über interne Verlinkung, Sie brechen nicht verlinken, aber der compiler kann nicht Beseitigung der Duplikate. Ich habe einmal Rasiert 8 MB aus einer ausführbaren Datei, durch entfernen der Definitionen von strings aus Kopf.
InformationsquelleAutor Philipp
Habe ich versucht, die notwendigen Informationen direkt aus der C++03 Standard-Dokument. Hier ist was ich gefunden habe:
Über die
const static
Erklärungen:Gemäß Abschnitt 3.5.3 definierten Objekte auf namespace-Ebene und erklärt
const
haben interne Verlinkung standardmäßig.static
auch deklariert einen namespace-level-Objekt, intern verknüpft, so gibt es keine Notwendigkeit zu erklären, ein Objektstatic const
.Ebenfalls nach Anhang D. 2
Bezüglich der statischen Initialisierung Fiasko:
Da die Variablen sind definiert in der header-Datei werden Sie immer definiert werden, bevor irgendeine andere statische Objekte, die Sie verwenden.
Aus Abschnitt 3.6.2.1:
Antwort 1: Dies bedeutet vorbei der Variablen zu einem statischen Objekt constuctor sollte in Ordnung sein.
Antwort 2: Jedoch ein problem auftreten könnte, wenn die Variablen verwiesen wird, die von einer nicht-inline-Konstruktor, der ein statisches Objekt:
Weder in Abschnitt 3.6.2.1 noch 3.6.2.3 ist es angegeben, in welcher Reihenfolge die statischen Objekte in verschiedenen compilation units initialisiert wenn dynamische Initialisierung abgeschlossen ist, bevor die erste Anweisung des
main
.Folgendes:
Seit
myclass.cpp
hat seine eigene Kopie derconst
Variablen, könnten diese nicht initialisiert, wennMyClass::MyClass()
genannt wird.Also ja,
const
definierten Variablen in header-Dateien können in einer Weise verwendet werden, die anfällig für die statische Initialisierung FiaskoSoweit ich sehen kann, gilt dies nur für Variablen, die nicht erfordern, statische Initialisierung:
Aus C++03-standard, Abschnitt 3.6.2.1:
InformationsquelleAutor Hanno S.
Was bezeichnet wird als die statische Initialisierung Fiasko ist ein problem, wenn ein namespace-level-Variablen ist abhängig vom Wert zugewiesen zu einem anderen namespace-Ebene-variable, die kann oder nicht initialisiert werden, bevor. In deinen beiden Beispielen gibt es keine solche Abhängigkeit, und es sollte kein problem sein.
Diese, auf der anderen Seite, ist anfällig für diese Art von Fehler:
Gibt es keine Garantie, dass
foo
wird initialisiert werden, bevorfoobar
, auch wenn beide konstant sind. Das bedeutet, dass das Verhalten des Programms ist undefiniert, und es könnte durchaus print "foobar", "bar" oder sterben.Ich würde es nicht Wagen, zu äußern. Mein Erster Gedanke ist, dass es in Ordnung sein sollte (die Konstante ist lokal für die übersetzungseinheit definiert wird, bevor die zweite Konstante), würde ich aber wenn möglich vermeiden, dass konstruieren. Der einfachste Weg den ich kenne um sicher zu sein, wäre mit einer Funktion mit einer static-variable intern statt der globalen var:
inline myclass& global_object() { myclass instance; return instance; }
Die Sprache garantiert, dassinstance
wird vollständig initialisiert ist, beim ersten Aufruf der Funktion, sostd::string other( global_object().Get() );
wird sicherlich funktionieren...Jedenfalls würde ich wirklich versuchen Sie zu vermeiden, Sie ganz zu beseitigen und die namespace-Ebene-Variablen mit Ihrer Initialisierung. Initialisierung der namespace-Ebene-Variablen ist nicht trivial, es geschieht in zwei Durchgängen, wo alle globals, die instanziiert werden aus Konstanten Ihre Werte zuerst, und dann in einem zweiten Durchlauf alles, was ist, ist abhängig von nicht-Konstanten initialisiert werden entsprechend der Reihenfolge der definition (innerhalb der gleichen übersetzungseinheit), in einer unbestimmten Reihenfolge, wenn mehr als eine übersetzungseinheit verbunden ist, die in ein Programm.
Separate Zusammenstellung ist wahrscheinlich der Schuldige. In Python geben, die Sie haben zu zählen und die Dinge sind exakt ausgeführt, wie Sie interpretiert werden. Sie kann sich nur auf etwas, das bereits definiert wurde. In Java-erstellen Sie eine source-Datei für die generierten .Klasse, und wieder das stellt eine klare Hierarchie für die Objekt-Dateien. In C oder C++ Sie erstellen separate übersetzungseinheiten gegen Erklärungen, der linker nicht weiß, wie zu bestellen, diese. Nicht zu erwähnen, dass es eventuell nicht in Ordnung ist, können Sie (auch wenn Sie nicht sollte) haben zyklische Abhängigkeiten zwischen TUs
das ist schwer zu sagen... wie? Module, glaube ich, wird dazu beitragen, in diese Richtung, aber Sie haben zu bauen, in einem völlig anderen Modus, hemmt zirkuläre Abhängigkeiten (z.B. Kopf-vs. implementation-Dateien) und haben einen Mechanismus, um zu verfolgen, welche hängt davon ab, was sonst. Module sind in dieser Linie, aber Sie nicht blockieren Sie das Problem, und Sie haben zu Leben, wie es für die Abwärtskompatibilität. C++ ist fast voll abwärtskompatibel, das ist eines der zentralen Kriterien in der standard committee. Jede wichtige änderung ist sorgfältig gewichtet: wie viele Menschen betroffen sein werden, und was die Lösung ist
InformationsquelleAutor David Rodríguez - dribeas
Statische Initialisierung Fiasko bezieht sich auf statische Variablen, die abhängen jeder andere. Lediglich die Definition einiger
static const
Variablen nicht eine Quelle von Problemen sein.InformationsquelleAutor Puppy