Merkmale der Sprache mql5, Feinheiten und Techniken - Seite 151

 
fxsaber:

Die statische Variable wird beim ersten Aufruf initialisiert.

Es ist schwer zu erraten, warum die Entwickler dies getan haben, ich denke, es ist ein Fehler - die Initialisierung einer konstanten Variablen mit einem unbekannten Wert zur Kompilierzeit

So überprüfe ich normalerweise, was und wann ich es initialisieren muss

//+------------------------------------------------------------------+
void OnStart()
{
   f(333);
   f(2);
}
//+------------------------------------------------------------------+
int init_static()
{
   Print(__FUNCTION__);
   return(1);
}

void f( const int i )
{
  static const int j = init_static();
  
  Print(__FUNCTION__," , j =",j);
}

2019.11.30 11:09:32.456 tst (EURUSD,H1) init_static

2019.11.30 11:09:32.457 tst (EURUSD,H1) f , j =1

2019.11.30 11:09:32.457 tst (EURUSD,H1) f , j =1


In meinem Beispiel wurde alles korrekt initialisiert und der Compiler erlaubt es nicht, der Konstante j einen weiteren Wert zuzuweisen - es wird ein Kompilierungsfehler auftreten

 
Vladimir Simakov:

Das Problem ist, dass es sich in jedem Fall nicht lohnt, sie zu verwenden, da es sich um einen konzeptionellen Fehler handelt.

Nun, es lohnt sich sowieso nicht, ihn zu verwenden, weil er ein begrifflicher Fehler ist.

 
Alexey Navoykov:

Sie sollten es ohnehin nicht verwenden, da es ein konzeptioneller Fehler ist.

Aber warum konzeptionell? Im Gegenteil, manchmal weiß man nicht, welchen Wert man bei der Kompilierung einer statischen Variable initialisieren soll, dann hilft die Initialisierung beim ersten Aufruf.

 
Alexey Navoykov:

Verwenden Sie es trotzdem nicht, denn es ist ein begrifflicher Fehler.

Implementierung von MVS C++17:

Statische lokale Variablen

Variablen, die im Blockbereich mit dem Spezifizierer static oderthread_local (seit C++11) deklariert werden, haben eine statischeoder thread (seit C++11) Speicherdauer, werden aber beim ersten Kontrolldurchlauf durch ihre Deklaration initialisiert (es sei denn, ihre Initialisierung ist eine Null- oder Konstantinitialisierung, die vor dem ersten Eintritt in den Block durchgeführt werden kann). Bei allen weiteren Aufrufen wird die Erklärung übersprungen.

Wenn die Initialisierung eine Ausnahme auslöst, gilt die Variable als nicht initialisiert und die Initialisierung wird beim nächsten Kontrolldurchlauf durch die Deklaration erneut versucht.

Wenn die Initialisierung rekursiv in den Block eintritt, in dem die Variable initialisiert wird, ist das Verhalten undefiniert.

Wenn mehrere Threads gleichzeitig versuchen, dieselbe statische lokale Variable zu initialisieren, erfolgt die Initialisierung genau einmal (ein ähnliches Verhalten kann für beliebige Funktionen mit std::call_once erreicht werden).

Hinweis: Übliche Implementierungen dieses Merkmals verwenden Varianten des doppelt geprüften Sperrmusters, das den Laufzeit-Overhead für bereits initialisierte lokale Statiken auf einen einzigen nicht-atomaren Booleschen Vergleich reduziert.

(seit C++11)

Der Destruktor für eine statische Block-Scope-Variable wird beim Programmende aufgerufen, aber nur, wenn die Initialisierung erfolgreich war.

Funktionslokale statische Objekte in allen Definitionen derselben Inline-Funktion (die implizit inline sein kann) beziehen sich alle auf dasselbe Objekt, das in einer Übersetzungseinheit definiert ist.

Ich persönlich bin dafür, wenn eine solche Implementierung in mql legal ist, man muss es nur in den Docs angeben.

 
Vladimir Simakov:

Warum ist sie also konzeptionell? Im Gegenteil, manchmal weiß man nicht, mit welchem Wert man eine statische Variable zur Kompilierzeit initialisieren soll, dann hilft die Initialisierung beim ersten Aufruf.

Wir müssen also mit einem Nullwert (Standardwert) initialisieren. Und warum mit dem ersten gefundenen Wert initialisieren? Dann wird das Verhalten der Funktion durch die Reihenfolge der Aufrufe dieser Funktion bestimmt, was einen Nebeneffekt hat. Und das ist falsch. Wenn Sie Interna von außen initialisieren wollen, sollten Sie eine Klasse und keine Funktion verwenden.

Allerdings habe ich mich geirrt, als ich sagte, dass es nicht kompiliert werden kann. In C++ funktioniert es seltsamerweise, obwohl ich nie auf die Idee gekommen wäre, so etwas zu tun.

 
Alexey Navoykov: In C++ funktioniert das seltsamerweise, obwohl ich nie auf die Idee gekommen wäre, das zu tun.

Das war schon immer so, es gibt keine konzeptionellen Probleme, das Problem wäre, wenn es anders wäre.

void fn() {
   static int i = fn_from_other_cpp();
}

Und die Reihenfolge der Zerstörung ist genau das Gegenteil.

 
Vict:

Das war dort schon immer so, keine konzeptionellen Probleme, es gäbe Probleme, wenn es anders wäre.

Ihr Beispiel ist ein wenig anders.
 
Slava:

Nach Auswahl des Kontextmenüs "Bearbeiten" findet der Navigator das Original mq5 nicht im gleichen Pfad wie ex5.

Weil ex5 von Shared Projects, wo sich mq5 befindet, in den Ordner scripts verschoben wurde

Ich werde es reparieren. Lassen Sie uns die gleiche intelligente Suche wie in den Testereinstellungen durchführen

Es gibt auch eine umgekehrte Situation. Im Favoriten-Navigator ist es nicht möglich, zur mq5-Bearbeitung zu gehen (mq5 ist verfügbar), wenn ex5 fehlt (z. B. wegen eines Kompilierungsfehlers). Bitte beheben Sie auch dies.

 
fxsaber:

Es gibt auch eine umgekehrte Situation. Im Favoriten-Navigator ist es nicht möglich, zur mq5-Bearbeitung zu wechseln (mq5 ist verfügbar), wenn ex5 fehlt (z.B. wegen eines Kompilierungsfehlers). Bitte beheben Sie auch dies.

2250 ist in Ordnung.

Es wurde überstürzt. 2251 - mq5 wird nicht geöffnet.

 
fxsaber:

2250 ist in Ordnung.

Eilig. 2251 - mq5 wird nicht geöffnet.

Ist sie da? Haben Sie es? Auf welchem Weg befindet sie sich?

Wie kann sie reproduziert werden?