Fehler, Irrtümer, Fragen - Seite 1951

 
Stanislav Korotky:

Gibt es eine Möglichkeit, eine anonyme Objektinstanz aus einer Funktion zurückzugeben?

Ersetzen Sie es durch ein Makro.
 
fxsaber:
Ersetzen Sie es durch ein Makro.

Es wird nicht funktionieren. Es handelt sich hierbei um eine Klassenmethode, und param wird tatsächlich vom Objekt übernommen. Ich habe es hier zum Beispiel vereinfacht.

 
Stanislav Korotky:

Es wird nicht funktionieren. Es handelt sich hierbei um eine Klassenmethode, und param wird tatsächlich vom Objekt übernommen. Ich habe es hier zum Beispiel vereinfacht.

Es ist natürlich besser, wenn Sie sich mit der ursprünglichen Aufgabe vertraut machen...

Wäre es falsch, einen Zeiger zurückzugeben?

 

Stanislav Korotky:

Es funktioniert, außer dass es eine zusätzliche interne Kopie erstellt unddie Rückgabeanweisung einen Kopierkonstruktor in der Klasse erfordert. Obwohl die Kopie beim Beenden der Funktion festgenagelt wird, würde ich das Kopieren selbst gerne eliminieren.


Class function()
{
  int param = 0;
  Class obj(param);
  return obj;
}

Natürlich, die lokale Variable wird zerstört, wenn die Funktion beendet wird.
Verwenden Sie new und geben Sie den Zeiger zurück, wo liegt das Problem?

Wenn Sie die Kontrolle über die Ressourcen benötigen, verwenden Sie einen Wrapper wie Smart Pointer.
Vielleicht könnten Sie etwas aus Creational Patterns wie Singleton oder Builder verwenden...

 
fxsaber:

Es ist natürlich besser, sich mit der ursprünglichen Aufgabe vertraut zu machen...

Wäre es falsch, den Zeiger zurückzugeben?

Das war ursprünglich auf Zeigern. Aber dann ist der Client-Code dafür verantwortlich, sie zu entfernen, und das ist eine Menge Müll, ganz zu schweigen von der Tatsache, dass es nur einen Wimpernschlag dauert, und schon hat man keine Links mehr.

 
Sergey Dzyublik:

Natürlich, nach Beendigung der Funktion wird die lokale Variable zerstört.

Verwenden Sie new und geben Sie einen Zeiger zurück, wo liegt das Problem?

Wenn Sie die Kontrolle über die Ressourcen benötigen, verwenden Sie einen Wrapper wie Smart Pointer.
Vielleicht ist etwas aus Creational Patterns wie Singleton oder Builder für Sie geeignet.

Zeiger sind da - unbequem (Antwort oben). Ich habe versucht, in Richtung "Intelligenz" zu schauen. Ich habe jedoch den Eindruck, dass ein intelligenter Zeiger für MQL nur eine weitere Ebene der Referenzialität schafft, die ihrerseits überwacht werden muss. Denn was ist ein intelligenter Zeiger? - Es handelt sich um ein Wrapper-Objekt, in dem die ursprüngliche Referenz platziert wird. Und wer und wann wird die Verpackung gereinigt? ;-) Wenn Sie fertige Lösungen haben, schreiben Sie mir bitte eine Nachricht. Ich habe einen Testfall für jetzt.

 
Stanislav Korotky:

Denn was ist ein intelligenter Zeiger? - Es handelt sich um ein Wrapper-Objekt, in dem die ursprüngliche Referenz untergebracht ist. Und wer und wann wird die Verpackung gereinigt? ;-) Wenn Sie fertige Lösungen haben, schreiben Sie mir bitte eine Nachricht. Ich habe einen Testfall für jetzt.


Shared_ptr verwenden.
Sie brauchen diesen Wrapper nicht zu säubern, Sie kopieren ihn einfach und shared_ptr gibt an, wie viele Instanzen der gewünschten Ressource übrig sind und wann diese oder jene Ressource freigegeben werden soll.


Es gibt keine vorgefertigten Lösungen, zumindest nicht für mich. C++ anpassen.

 
Sergey Dzyublik:

Es gibt keine vorgefertigten Lösungen, zumindest nicht für mich. Passen Sie die C++-Dateien an.

Es ist verständlich - das ist, was ich tue, aber ich habe bereits den Eindruck, dass MQL nicht erlauben, "Tracing" zu machen.

 
Stanislav Korotky:

Gibt es eine Möglichkeit, eine anonyme Objektinstanz aus einer Funktion zurückzugeben?

Wie bereits jemand hier dargelegt hat, ist der korrekteste Weg, einen intelligenten Zeiger aus einer Funktion zurückzugeben. All dies ist in MQL implementiert. Es ist zwar nicht so bequem zu verwenden wie in C++, weil pass by pointer über eine Methode implementiert werden sollte, anstatt über den pass-Operator. Übrigens, für die vorliegende Aufgabe ist shared_ptr wohl nicht notwendig, unique_ptr reicht aus.

Alternativ könnte der in der Funktion erzeugte Zeiger sofort in einem globalen Array abgelegt werden, das am Ende des Programms gelöscht wird. Gleichzeitig kann der Benutzer den Speicher des Objekts jederzeit durch den Aufruf einer speziellen Funktion freigeben (nicht löschen). Es ist wie CloseHandle in WinApi.

Es funktioniert, außer dass eine zusätzliche interne Kopie erstellt wird und der Rückgabeoperator einen Kopierkonstruktor in der Klasse erfordert. Obwohl die Kopie beim Beenden der Funktion festgenagelt wird, würde ich die Kopie selbst gerne eliminieren.

Vielleicht ist der Compiler klug genug, alles selbst zu optimieren und zu inlineen, um unnötiges Kopieren zu vermeiden. Aber wir müssen es überprüfen. Es wäre schön, wenn jemand Tests und Messungen durchführen würde. Denn auch ich befinde mich oft in einem solchen Dilemma.

 
Alexey Navoykov:

Wie bereits erwähnt, ist der richtige Weg, dies zu tun, einen intelligenten Zeiger aus einer Funktion zurückzugeben. All dies ist in MQL implementiert. Aber es ist nicht so bequem zu benutzen wie in C++, weil der Zeigerwechsel über eine Methode und nicht über einen Schalteroperator implementiert werden muss. Übrigens, für die vorliegende Aufgabe ist shared_ptr wohl nicht notwendig, unique_ptr reicht aus.

Alternativ könnte der in der Funktion erzeugte Zeiger sofort in einem globalen Array abgelegt werden, das am Ende des Programms gelöscht wird. Gleichzeitig kann der Benutzer den Speicher des Objekts jederzeit durch den Aufruf einer speziellen Funktion freigeben (nicht löschen). Es ist wie CloseHandle in WinApi.

Vielleicht ist der Compiler klug genug, alles zu optimieren und selbst zu inlineen, so dass unnötiges Kopieren entfällt. Aber wir müssen es überprüfen. Es wäre schön, wenn jemand Tests und Messungen durchführen würde. Ansonsten befinde ich mich auch oft in einem solchen Dilemma.

Ich veröffentliche meine Implementierung weiter unten - jedenfalls werden diese Smart-Pointer temporär erstellt, und als Ergebnis erzeuge und nagle ich einfach mehr Objekte als ich hatte ;-).

Natürlich habe ich im Sinn eine Variante der globalen Array, aber es ist so hässlich! Vor allem, weil ich durch Timer aufräumen wollte (weil das Programm für Tage laufen kann), und der Timer in MQL kann nicht an eine Klasse/Objekt angehängt werden - es kommt nur aus dem globalen Handler.

Der Compiler hilft hier nicht - getestet - das lokale Objekt wird per Return dupliziert und dann genagelt. In diesem Fall gibt es keinen optimalen Zug.

template<typename T>
class auto_ptr
{
  private:

    class Reference
    {
      public:
        int count;
        Reference(): count(0) {}
    };

    T *data;
    Reference *reference;

    void remove()
    {
      if(reference != NULL)
      {
        reference.count--;
        if(reference.count == 0)
        {
          delete data;
          delete reference;
        }
      }
    }

    
  public:
    auto_ptr(): data(NULL), reference(NULL)
    {
    }
    auto_ptr(T *ptr): data(ptr), reference(ptr == NULL ? NULL : new Reference())
    {
      if(reference != NULL) reference.count++;
    }
    auto_ptr(auto_ptr<T> &ref): data(ref.data), reference(ref.reference)
    {
      reference.count++;
    }
    
    ~auto_ptr()
    {
      remove();
    }
    
    void operator=(auto_ptr<T> &next)
    {
      if(&this != &next)
      {
        remove();
        
        data = next.data;
        reference = next.reference;
        reference.count++;
      }
    }
};