Location für den Destructor



  • Ich habe eine Klasse die auf einem directory arbeitet, was weitere subdirectories voller tiff-files enthält. Ich habe das so gelöst, dass mein DataHandler einen std::vector voller subdirectory objekte (definiert als nested class innerhalb der DataHandler-Klasse) enthält. Die Klasse subdirectory wiederum definiert eine struct, in der neben den eigentlichen tiff-daten auch metadaten gespeichert werden. Ich laufe über die direcotires mit der boost-filesystem library (hier zur Übersichtlichkeit ausgelassen)

    class DataHandler{
    
     private:
       struct Subdirectoryhandler{
        ...
    
        struct Tiff {
           uint16_t *pTiff{nullptr};
           int width{0};
           int height{0};
           int bitsPerSample{0};
           int samplPerPixel{0};
           int photoMetric{0};
           int sampleFormat{0};
         //  ~radarTiff() { delete[] pTiff; }
        };
       std::map<std::string, Tiff> Data_;
      }
     std::vector<SubdirectoryHandler> subdirectories_;
    }
    
    • Ist das so korrekt gelöst oder was wären bessere Wege? Möchte gerne mit einem header-file und einem source-file auskommen
    • der built-in pointer erfordert einen destruktor, ist dessen Definition innerhalb der Tiff-struct korrekt? Wenn ein Objekt vom typ Datahandler out-of-scope geht, löscht der vector seinen Inhalt, in diesem Fall die Referenzen auf die hinzugefügten SubDirectory-Objekte. Diese beinhalten maps, für die das gleiche gilt. Also dachte ich, der Destruktor muss innerhalb der Tiff-Struct definiert werden. Korrekt? oDer muss ich den in einer der übergeordeneten Klassen definieren?
    • die tiff-library arbheitet ja mit built-in pointern, aber kann ich die auch mit Smart-pointern handlen?

    Danke schon mal für eure Hilfe



  • die tiff-library arbheitet ja mit built-in pointern, aber kann ich die auch mit Smart-pointern handlen?

    Welche anderen Pointer benutzt du denn sonst mit Smartpointern?

    Libiff wird aber wohl eine C-Bibliothek sein und daher malloc/free verwenden. Dann muss der Smartpointer mit free aufräumen:

    #include <memory>
    #include <cstdlib>
    
    struct Free
    {
      void operator()(void* ptr)
      {
        free(ptr);
      }
    };
    
    int main()
    {
      std::unique_ptr<int, Free> x{ (int*)malloc( sizeof(int) ) };
    }
    

  • Mod

    manni66 schrieb:

    Libiff wird aber wohl eine C-Bibliothek sein und daher malloc/free verwenden. Dann muss der Smartpointer mit free aufräumen:

    Falls er libtiff verwendet: Die kommt, wie die meisten anderen C-Bibliotheken, mit ihrem eigenen Konstruktor bzw. Destruktor. Die kann man dann auch in einen Smartpointer oder sonstige Halterklasse stopfen.

    Es sieht aber irgendwie eher nach einer selbstgebauten Datenstruktur für Tiff aus. Da stellt sich wiederum die Frage, wieso überhaupt Pointer und kein Vector. Speicherverwaltung ist gewiss keine Aufgabe eines Bildes. Zumal es auch prompt falsch gemacht wurde, da Sewing wohl noch nie von der Rule of 0/3/5 oder RAII gehört hat.

    Da es recht geheimnisvoll ist, was der Threadersteller überhaupt für Techniken benutzt, kann ich leider nicht genauer helfen. Überhaupt ist das ganze Datenmodell komisch. Wieso ist Subdirectoryhandler eine Unterklasse von DataHandler? Wieso ist Tiff eine Unterklasse von Subdirectoryhandler? Was ist überhaupt die Aufgabe der beiden Handler?



  • Danke erstmal für eure Hilfe, benutze tiffio.h

    Ich habe einen Ordner, in dem viele Unterordner liegen. Jeder dieser Unterordner beinhaltet alle möglichen files: tiffFiles, , txtfiles, etc.

    Ich möchte jetztt das DataHandler mittels eines Vectors von Subdirectory Objekten, die Files (zB. tiff) innerhalb jedes Unterordners verwaltet.

    Wo brauche ich hier rule of 5? Es wird nichts kopiert im Betrieb später



  • Sewing schrieb:

    Wo brauche ich hier rule of 5? Es wird nichts kopiert im Betrieb später

    Doch, es wird kopiert. Deine Klasse DataHandler::Tiff hat einen Pointer ( pTiff ), der vermutlich auf die Bilddaten zeigt. Du hast eine std::map<std::string,Tiff> , die beim Einfügen Kopien erzeugt. Das kann bei der DataHandler::Tiff Klasse zu Problemen führen, wenn die Klasse für die Lebensdauer des Speichers verantwortlich ist, auf den pTiff zeigt.
    Wenn es kein besitzender Zeiger ist kannst du das so machen, aber dann stellt sich die Frage, wer später für das Freigeben des Speichers verantwortlich ist.



  • Auch wenn ich emplace verwende für die map?



  • Sewing schrieb:

    Auch wenn ich emplace verwende für die map?

    Nö.
    Aber die Rule of 3 besagt halt auch: wenn man keinen copy-ctor und assignment-operator implementieren kann (bzw. nicht will, weil man keinen braucht), dann hat man gefälligst etwas zu machen was das Generieren der Default-Varianten verhindert.
    Also = delete, private deklarieren (aber nicht definieren) oder ableiten von etwas wie boost::noncopyable. (Oder nicht kopierbare und nicht zuweisbare Member haben.)

    Einfach zu sagen "ja aber ich ruf den (kaputten) copy-ctor eh nicht auf" ist extremst ... pfui. Weil mittelfristig viel zu fehleranfällig.



  • werde ich beherzigen, danke!



  • Ist das so korrekt gelöst oder was wären bessere Wege? Möchte gerne mit einem header-file und einem source-file auskommen

    Was hat denn nun die Aufteilung in .h/.cpp mit dem Rest zu tun? Niemand hindert dich daran, alles in eine Datei zu schreiben und einfach eine leere .h (oder auch gar keine) zu includen. Eine Idee hinter der Aufteilung ist, dass du dann bestimmte Klassen einfach in mehreren Stellen (in unterschiedlichen .cpp-Dateien) wiederverwenden kannst. Du kannst das aber auch sein lassen, wenn du eh nur irgendwas schnell testen willst.

    Die Frage ist doch:
    Kann die Tiff-Klasse auch ohne die DataHandler sinnvoll sein bzw. müssen die Klassen irgendwas voneinander wissen? Die Antwort scheint bislang sehr klar "Nein" zu sein (du willst doch zum Beispiel sicher auch mal die Tiff-Klasse testen können, ohne erst groß irgendwas mit dem DataHandler machen zu müssen!). Was nicht zusammengehört, soll auch nicht abhängig voneinander sein! Das bedeutet, dass du haben solltest:

    struct Tiff {
        ...
    };
    
    class DataHandler {
        ...
    };
    

    Also KEINE Verschachtelung.

    DataHandler und Subdirectoryhandler erscheinen auch irgendwie merkwürdig so verschachtelt. Warum sind sie es? Verstehe nicht ganz, wofür die genau gut sein sollen.



  • hielt es irgendwie für angebracht 😕

    Kann aber die drei Klassen auch voneinander innerhalb einer header und einem source file trennen 🙂


Log in to reply