Ist es in C ++ gut, Code zu schreiben, der vor main () ausgeführt wird?

7

Die Konstruktoren von global deklarierten Klassen werden aufgerufen, bevor main eingegeben wird. Während dies für einen neuen Leser des Codes verwirrend sein kann, weil es so selten geschieht, ist es notwendigerweise eine schlechte Idee?

    
Bruce 24.06.2010, 14:38
quelle

7 Antworten

18

Es ist nicht unbedingt eine schlechte Idee, aber normalerweise, ja.

Erstens sind es globale Daten und Globals sind normalerweise eine schlechte Sache. Je globaler Sie sind, desto schwieriger wird es, über Ihr Programm nachzudenken.

Zweitens garantiert C ++ keine Initialisierungsreihenfolge von statischen Objekten, die in verschiedenen Übersetzungseinheiten (.cpp-Dateien) definiert sind. Wenn sie also voneinander abhängen, können Sie Probleme haben.

    
jalf 24.06.2010, 14:41
quelle
7

Ja, das ist schlecht. Da Sie keine Möglichkeit haben, Ausnahmen abzufangen und damit umzugehen, wird der Standard-Handler verwendet. In C ++ bedeutet das den Aufruf von terminate ...

Beispiel: Inhalt a.cpp

%Vor%

Ausgabe von: g++ a.cpp && ./a.out

%Vor%

Sie können versuchen, ein try ... catch in Ihrem main hinzuzufügen, das wird nicht helfen.

Bearbeiten: Jalfs Punkte sind auch gültig. Höre auf seinen Rat.

    
bltxd 24.06.2010 14:48
quelle
1

Zusätzlich zu der fraglichen Form - Es wird nicht auf einigen Plattformen portierbar sein.

    
Ofir 24.06.2010 14:43
quelle
1

Wie Sie betonen, ist es erlaubt. In der letzten Firma, in der ich gearbeitet habe, haben wir in einer solchen Situation die Politik gemacht, main () einen entsprechenden Kommentar hinzuzufügen, um anzugeben, für welche Variablen dies galt. Wenn Sie eine schlechte Situation haben, versuchen Sie, das Beste daraus zu machen.

    
Sparky 24.06.2010 14:43
quelle
0

Die Verwendung von globalen / statischen Objekten mit nicht-trivialen Konstruktoren und Destruktoren ist schrecklich . Ich habe genug riesige Software-Projekte gesehen, die sich in einer Katastrophe befanden, weil unkontrollierte globale / statische Objekte und Einzeltöne verwendet wurden.

Das Problem ist nicht die Tatsache, dass es der Code ist, der außerhalb von main ausgeführt wird. Es ist, dass diese Objekte in einer unkontrollierbaren Reihenfolge konstruiert und zerstört werden.

Außerdem glaube ich, dass es generell eine schlechte Praxis ist, globale Variablen (auch gewöhnliche Variablen) zu verwenden, mit einigen Ausnahmen. Jedes Stück Code sollte in einem gut definierten Kontext ausgeführt werden, und alle Variablen sollten dazu gehören.

    
valdo 24.06.2010 16:32
quelle
0

Es ist überhaupt keine schlechte Form und es ist nicht verwirrend. Die statische Initialisierung ist eine bewusste Eigenschaft der Sprache. Verwenden Sie es, wenn Sie müssen. Gleiches gilt für Globals. Verwenden Sie sie bei Bedarf. Wie jedes Feature ist es ein starker Programmierer, zu wissen, wann es angemessen ist und seine Grenzen zu kennen.

Schlechte Form restrukturiert ein ansonsten perfektes Programm, um Globals oder statische Initialisierung zu vermeiden.

    
John 24.06.2010 16:55
quelle
0
___ answer3111030 ___

Zusätzlich zu der fraglichen Form - Es wird nicht auf einigen Plattformen portierbar sein.

    
___ qstntxt ___

Die Konstruktoren von global deklarierten Klassen werden aufgerufen, bevor main eingegeben wird. Während dies für einen neuen Leser des Codes verwirrend sein kann, weil es so selten geschieht, ist es notwendigerweise eine schlechte Idee?

    
___ answer3111077 ___

Ja, das ist schlecht. Da Sie keine Möglichkeit haben, Ausnahmen abzufangen und damit umzugehen, wird der Standard-Handler verwendet. In C ++ bedeutet das den Aufruf von terminate ...

Beispiel: Inhalt %code%

%Vor%

Ausgabe von: %code%

%Vor%

Sie können versuchen, ein %code% in Ihrem main hinzuzufügen, das wird nicht helfen.

Bearbeiten: Jalfs Punkte sind auch gültig. Höre auf seinen Rat.

    
___ answer3111035 ___

Wie Sie betonen, ist es erlaubt. In der letzten Firma, in der ich gearbeitet habe, haben wir in einer solchen Situation die Politik gemacht, main () einen entsprechenden Kommentar hinzuzufügen, um anzugeben, für welche Variablen dies galt. Wenn Sie eine schlechte Situation haben, versuchen Sie, das Beste daraus zu machen.

    
___ answer3112127 ___

Es ist überhaupt keine schlechte Form und es ist nicht verwirrend. Die statische Initialisierung ist eine bewusste Eigenschaft der Sprache. Verwenden Sie es, wenn Sie müssen. Gleiches gilt für Globals. Verwenden Sie sie bei Bedarf. Wie jedes Feature ist es ein starker Programmierer, zu wissen, wann es angemessen ist und seine Grenzen zu kennen.

Schlechte Form restrukturiert ein ansonsten perfektes Programm, um Globals oder statische Initialisierung zu vermeiden.

    
___ answer3111912 ___

Die Verwendung von globalen / statischen Objekten mit nicht-trivialen Konstruktoren und Destruktoren ist schrecklich . Ich habe genug riesige Software-Projekte gesehen, die sich in einer Katastrophe befanden, weil unkontrollierte globale / statische Objekte und Einzeltöne verwendet wurden.

Das Problem ist nicht die Tatsache, dass es der Code ist, der außerhalb von %code% ausgeführt wird. Es ist, dass diese Objekte in einer unkontrollierbaren Reihenfolge konstruiert und zerstört werden.

Außerdem glaube ich, dass es generell eine schlechte Praxis ist, globale Variablen (auch gewöhnliche Variablen) zu verwenden, mit einigen Ausnahmen. Jedes Stück Code sollte in einem gut definierten Kontext ausgeführt werden, und alle Variablen sollten dazu gehören.

    
___ tag123c ___ C ++ ist eine universelle Programmiersprache. Es wurde ursprünglich als Erweiterung von C entworfen und behält eine ähnliche Syntax, ist aber jetzt eine komplett andere Sprache. Verwenden Sie dieses Tag für Fragen zu Code, der mit einem C ++ - Compiler kompiliert werden soll. ___ tag123constructor ___ Eine spezielle Art von Subroutine, die bei der Erstellung eines Objekts aufgerufen wird. ___ qstnhdr ___ Ist es in C ++ gut, Code zu schreiben, der vor main () ausgeführt wird? ___ answer3113130 ​​___

Ich werde so weit gehen müssen zu sagen, dass es eine schlechte Form für Nicht-PODs ist, besonders wenn Sie in einem Team arbeiten, hauptsächlich aufgrund von Problemen bei der Initialisierung, die leicht daraus entstehen können.

%Vor%

Menschen schreiben im Allgemeinen keinen Code wie oben, sondern überlegen, ob der Erfolg mit dem Rückgabewert einer anderen Funktion initialisiert wurde. Jeder, der versucht hat, cout oder cerr oder ein anderes globales Objekt in dieser Funktion zu verwenden, hat das gleiche undefinierte Verhalten ausgelöst.

Berücksichtigen Sie bei benutzerdefinierten Typen mit Konstruktoren und Destruktoren die alternative Methode, bei der der Zugriff initialisiert wird:

%Vor%

Leider hat dies auch Probleme mit der Thread-Sicherheit, so dass ein Sperrmechanismus für den Aufbau von 'f' erforderlich ist, wenn Sie gleichzeitig auf safe_static zugreifen.

Das heißt, ich denke, man sollte versuchen, die Dinge einfach zu halten. Leider ist es bei benutzerdefinierten Objekten, die im Dateibereich definiert sind, viel zu einfach, in ein undefiniertes Verhalten zu geraten. Der kleine zusätzliche Aufwand, um etwas wie safe_static oben zu schreiben, kann viele Kopfschmerzen verhindern.

Ausnahmen sind ein anderer Punkt. Wenn Ihre statischen Objekte den Konstruktor verlassen, haben Sie keine Möglichkeit, die Ausnahme abzufangen. Wenn Sie möchten, dass Ihre Anwendung wirklich robust ist und sogar Startfehler behandelt, müssen Sie Ihren Code sorgfältig strukturieren (z. B. try / catch-Blöcke in den Konstruktoren für die Objekte, die Sie im Dateibereich erstellen, sodass die Ausnahme nicht ausgelöst wird außerhalb des ctor und vermeiden auch Initialisierungslisten, die werfen).

Wenn Sie in einem Team arbeiten, denken Sie vielleicht an sich selbst: "Oh, ich greife nicht auf irgendwelche anderen Globals in meiner Klasse zu, ich könnte es genauso gut zu einem einfachen globalen System mit interner Verknüpfung im Dateibereich machen." Das mag dann stimmen, aber bevor Sie es wissen, fügt Ihr Kollege eine weitere globale Variable hinzu und versucht, darauf vom Konstruktor Ihrer Klasse zuzugreifen. Plötzlich haben Sie ein undefiniertes Verhalten, das möglicherweise nicht einmal ein Problem auf der Hauptplattform darstellt, auf die Sie nur abzielen, wenn Ihr Code abstürzt und andere seltsame Dinge tut, wenn Sie versuchen, Ihren Code anderweitig zu portieren.

Es ist wirklich nicht die potenziellen Kopfschmerzen IMO wert, und es ist ein Problem, das viel einfacher zu vermeiden als zu beheben ist.

    
___ answer3111007 ___

Es ist nicht unbedingt eine schlechte Idee, aber normalerweise, ja.

Erstens sind es globale Daten und Globals sind normalerweise eine schlechte Sache. Je globaler Sie sind, desto schwieriger wird es, über Ihr Programm nachzudenken.

Zweitens garantiert C ++ keine Initialisierungsreihenfolge von statischen Objekten, die in verschiedenen Übersetzungseinheiten (.cpp-Dateien) definiert sind. Wenn sie also voneinander abhängen, können Sie Probleme haben.

    
___
stinky472 24.06.2010 19:09
quelle

Tags und Links