Zeiger auf ein Element aus std::map zurückgeben



  • @Swordfish sagte in Zeiger auf ein Element aus std::map zurückgeben:

    Hast Du mal einen Link zur Doku der entsprechenden Funktionen?

    Hier mal die Version des AOS3.x, die ich nutze, um abwärtskompatibel zu sein:
    AllocBitMap
    Der Link zur Freigabefunktion ist unten auf der Seite angegeben.
    Für das "Einsetzen" der Grafik nutze ich dann noch einen RastPort (der muss mit InitRastPort initialisiert werden), lokale temporäre BitMaps und WriteChunkyPixels, sowie GetBitMapAttr und CopyMem).
    Hier hab ich auch schon erste Inkonsistenzen, da ich noch eine RastPort-Kapselklasse gemacht habe, um einfachere Methoden für Clipping und Blitten anzubieten (aber die sind wohl dann zu "einfach", da noch nicht alle möglichen Parametrierungen nach außen gelegt sind - sie können also viel weniger als die Originalfunktionen, -strukturen etc.). Dazu nutze ich diese RastPort-Kapselklasse z.B. nicht in Frame für die Initialisierung, da mir dort eine einfache RastPort-Struktur des Systems reicht (sie wird nur als Zwischenpuffer genutzt - Objekte der Kapselklasse kapseln eher die Funktionen, die das System für RastPorts anbietet, nicht die RastPort-Struktur).
    Aber zu den Punkten kann ich noch sehr viel sagen, das Design ist sicher nicht so prall.

    Warum? Wieso soll Dein Code nicht auch als Hausnummer C++14 kompilieren?

    Na das sollte er! ☺ Ich dachte da eher so an Sachen, wie Nutzung von auto, anstelle der kaum lesbaren alten Schreibweise für STL-Iteratoren, smartpointer, Nutzung von Range-based-for, Initializer-Arrays, constexpr und was es noch so alles gibt. Keine Ahnung, ob ich die auch wirklich alle nutzen sollte, bzw. in welcher Reihenfolge man die dann am besten bzgl. Portierung angeht.



  • Gerade solche Allokations- und Deallokationsfunktionen (als Paar) sind doch perfekt für RAII, also diese beide in einer Klasse kapseln.
    Und dann kannst du ein Objekt dieser Klasse direkt in der Anwendungsklasse (z.B. FrameC) benutzen.



  • @Th69 sagte in Zeiger auf ein Element aus std::map zurückgeben:

    Gerade solche Allokations- und Deallokationsfunktionen (als Paar) sind doch perfekt für RAII, also diese beide in einer Klasse kapseln.
    Und dann kannst du ein Objekt dieser Klasse direkt in der Anwendungsklasse (z.B. FrameC) benutzen.

    Also wenn ich mir den Wiki-Artikel anschaue, dann entspricht doch FrameC schon dem Pattern, oder nicht?
    Im Wiki Bsp. wird eine Dateiklasse erstellt, welche die Verwaltung der Systemressource FILE übernimmt. Darin enthalten ist auch eine Ausgabe (also nicht nur reines öffnen und schließen). Bei FrameC ist es quasi ähnlich. Die Klasse verwaltet die BitMap und ist gleichzeitig auch für die Darstellung gedacht (kann geblittet werden). Was wäre denn der Vorteil, wenn ich da noch eine Indirektion einführe und eine weitere Klasse mache, die nur eine BitMap alloziert und wieder freigibt?
    Ich müsste quasi alle Parameter des FrameC-Konstruktors and diese neue Klasse weiterreichen und auch die Hälfte der getter (für die Bild- und Maskendaten). Damit ist dann fast alles doppelt vorhanden (ich kann die Klasse auch gern mal hier rein stellen).

    Allerdings habe ich an anderen Stellen, bei denen ich BitMaps und andere Systemressourcen nur kurz als Hilfsmittel verwende, diese direkt in den Methoden benutzt (da ich sie dort nicht als Frame gebraucht habe, sondern, um z.B. temporär einen Puffer fürs double-buffering zu erzeugen).



  • Ok, dann muss ich meine Eingangsfrage nochmal aufgreifen und anpassen:

    Wenn ich eine Referenz auf einen Vector in der Map zurückgeben möchte, aber verhindern will, dass bei Nicht-Finden eines Eintrages automatisch ein leerer angelegt wird - wie geht man dann vor, damit keine ungültige Referenz entsteht? Eine Exception werfen?

    Also ungefähr so:

            std::map<const int, std::vector<FrameC *> >::const_iterator resultIt = frameCollections.find(frameCollectionID);
    	
    	// nur wenn was gefunden wurde 
    	if (resultIt != frameCollections.end())
    	{
        	    return (resultIt->second);
            }
    	
    	throw xyz;
    


  • @Th69 sagte in Zeiger auf ein Element aus std::map zurückgeben:

    Gerade solche Allokations- und Deallokationsfunktionen (als Paar) sind doch perfekt für RAII, also diese beide in einer Klasse kapseln.
    Und dann kannst du ein Objekt dieser Klasse direkt in der Anwendungsklasse (z.B. FrameC) benutzen.

    Muss das nochmal ausgraben: Gäbe es hier ein (kleines) Beispiel dazu (Link reicht auch)?



  • @Reth sagte in Zeiger auf ein Element aus std::map zurückgeben:

    Zurückgeben möchte ich einen Zeiger auf einen Vektor, ...

    Zeiger gehören NICHT in C++ler Hände, C++ wurde genau deswegen (von einem Theoretiker) erschaffen, um eben NICHT mit solchem Teufelszeug umgehen zu müssen; quasi damit auch Semiprofis von sich behaupten können, programmieren zu können im Gegensatz zu Vollprofis (besser gesagt Praktiker), denen das ganze "Teufelszeug" in Fleisch und Blut übergegangen ist.
    Resultat solcher "ich programmiere in C/C++" -Versuche sind dann genau solche Fragestellungen, wie du sie hier gerade aufwirfst.



  • @Wutz
    Das hilft mir jetzt wenn, dann nur bedingt. Hauptgrund war/ist, dass ich nicht alles kopieren möchte zum einen, zum anderen handhabe ich hier mit einer API (AmigaOS wurde bereits weiter oben im Thread erwähnt), die es nur ermöglicht über Zeiger und weiteres zu Arbeiten. Schon allein aus diesem Grund m u s s ich mit Zeigern in C++ arbeiten (oder was empfiehlst Du oder der Theoretiker an dieser Stelle, wie damit umgegangen werden sollte? Reines C verwenden?)!



  • @Wutz

    Vollprofis

    ROTFL



  • @Reth sagte in Zeiger auf ein Element aus std::map zurückgeben:

    Reines C verwenden?

    !
    Zumindestens dass du dir Wrapper schreibst, die das direkte Hantieren von Zeigern und C++Zeugs verhindern und sauber kapseln.



  • @Wutz sagte in Zeiger auf ein Element aus std::map zurückgeben:

    Zumindestens dass du dir Wrapper schreibst, die das direkte Hantieren von Zeigern und C++Zeugs verhindern und sauber kapseln.

    Genau. Und hier sind wir in einem solchen Wrapper. Klar verwende ich hier Zeiger auf C++-Konstrukte und nicht nur die der darunter liegenden API, aber ist das wirklich nicht vorgesehen/guter Stil? Die Alternative bei Containern ist ja eine Kopierorgie mit entsprechendem Overhead an Speicherverbrauch und Laufzeit (auch wenn beides heutzutage nicht mehr so die ganz große Rolle spielt ist es gerade bei älteren Systemen deutlich relevanter)!
    Oder würde man da ganz anders ran gehen?

    Und dann nochmal die Frage:
    @Th69 sagte in Zeiger auf ein Element aus std::map zurückgeben:

    Gerade solche Allokations- und Deallokationsfunktionen (als Paar) sind doch perfekt für RAII, also diese beide in einer Klasse kapseln.
    Und dann kannst du ein Objekt dieser Klasse direkt in der Anwendungsklasse (z.B. FrameC) benutzen.

    Gibt es hier ein gutes Bsp. für, das ich mir anschauen könnte? Eine allgemeine Klasse für so etwas kann ich ja nicht basteln, da alle Ressourcen eigene Allokations- und Freigabefunktionen haben. Für Ressourcen gleicher Art (Libraries, Fenster, Screens, BitMaps, RastPorts, etc.) hab ich mir schon Verwalterklassen gebaut, die damit umgehen können, so dass man als "Verwender" sich nicht mehr mit den Interna des Betriebssystems und seiner API herumschlagen muss (wie sauber und gut mir das gelungen ist, kann ich nichtmal sagen - hab im Entwerfen von Wrapper-APIs für andere APIs, Betriebssystemfunktionskapselungen usw. nicht wirklich Erfahrung...).



  • @Reth
    Wenn du betriebssystemnah und mit Zeigern programmieren willst/musst, du dir deiner Zeigerkenntnis aber nicht sicher bist, dann suche dir ein anderes Hobby und versuche nicht, mehrere Sprachkonzepte miteinander zu vermengen - du wirst schnell den Überblick verlieren.
    Warum glaubst du wohl, haben die Entwickler deines Amiga-OS Zeiger als API gewählt und bieten keine C++ API an? Eben weil sie selbst solchen Wrapping-Aufwand gescheut haben - und lieber nativ bleiben. Du aber willst sowas basteln - na dann viel Erfolg.



  • @Wutz sagte in Zeiger auf ein Element aus std::map zurückgeben:

    @Reth
    Wenn du betriebssystemnah und mit Zeigern programmieren willst/musst, du dir deiner Zeigerkenntnis aber nicht sicher bist, dann suche dir ein anderes Hobby und versuche nicht, mehrere Sprachkonzepte miteinander zu vermengen - du wirst schnell den Überblick verlieren.
    Warum glaubst du wohl, haben die Entwickler deines Amiga-OS Zeiger als API gewählt und bieten keine C++ API an? Eben weil sie selbst solchen Wrapping-Aufwand gescheut haben - und lieber nativ bleiben. Du aber willst sowas basteln - na dann viel Erfolg.

    Das mit dem "Durcheinanderbringen" bleibt doch gar nicht aus, wenn man mit C++ programmiert und dabei die API des Host-Systems anspricht und diese "nur" in Form von C Formaten (inkl. Zeigern vorliegt). Wieso die API, die ich verwende nicht nicht in C++ programmiert wurde, weiss ich nicht - aber bestimmt nicht, weil die Entwickler das so gewählt hatten, um den Wrapperaufwand zu sparen, vllt. eher weil das System und seine API zu einer Zeit entstanden sind, zu der C++ noch nicht so etabliert war und/oder es dafür noch nicht so gute Tools gab, wie sie z.B. für C zur Verfügung standen (natürlich wuden das System und die API weiterentwickelt, aber verständlicherweise nicht einfach auf C++ portiert - bestand ja kein Grund dazu...).



  • Wenn FrameC bei dir schon die Wrapperklasse für BitMap ist, dann ist ja gut. Andererseits schreibst du, daß du an anderer Stelle wieder die C-API Funktionen dafür benutzt (und dann ist es doch besser, die Kapselung an genau einer Stelle zu haben).
    Du mußt auch nicht alle C-API Funktionen direkt kapseln, sondern eben nur die Alloc/Deallocfunktionen und im Wrapper kannst du ja trotzdem einen Zeiger auf die interne Resource (lesend) zur Verfügung stellen.

    Kannst ja mal eine der Wrapperklassen hier zeigen, damit ich mir besser ein Bild davon machen kann.

    PS: Ich habe schon vor mehr als 25 Jahren eine auf der "Intuition-Library" (bzw. den anderen Amiga-OS Libraries) basierenden Lib entworfen (aber auch noch in C) und diese dann einfach "i.lib" (in Anlehnung an "c.lib" und "m.lib") genannt: "-li -lm -lc". 😉
    Hauptsächlich um den Anwendungscode von den ganzen internen Strukturen wie NewScreen oder NewWindow zu befreien:

    Open_Screen(640,256,4,0x8000,"MyScreen");
    window0=Open_Window(0,11,640,245,"My Window",0x1000L,0x140L,0L,screen);
    

    sowie z.B. Laden und Speichern von IFF (ILBM)-Bildern.
    Der Vorteil dieser Lib war dann (wenn auch damals nicht so geplant), daß ich diese einfach nach Windows portieren konnte (dann aber intern mit C++ erstellt) und somit laufen auch meine auf dem Amiga damit erstellten Programme unter Windows.



  • @Reth sagte in Zeiger auf ein Element aus std::map zurückgeben:

    @Wutz sagte in Zeiger auf ein Element aus std::map zurückgeben:

    Zumindestens dass du dir Wrapper schreibst, die das direkte Hantieren von Zeigern und C++Zeugs verhindern und sauber kapseln.

    Genau. Und hier sind wir in einem solchen Wrapper. Klar verwende ich hier Zeiger auf C++-Konstrukte und nicht nur die der darunter liegenden API, aber ist das wirklich nicht vorgesehen/guter Stil? Die Alternative bei Containern ist ja eine Kopierorgie mit entsprechendem Overhead an Speicherverbrauch und Laufzeit

    Zeiger sind nur dann notwendig, wenn man gezwungen ist, ältere Compiler (vor C++11-Standard ) zu verwenden.
    Ab C++11 gibt es Smart-Pointer, die die ganze Sauerei kapseln und etwas entschärfen.

    Kopierorgien gibt es bei Containern auch nicht mehr wirklich. Dank Move-Semantik und RVO ist da auch einiger flotter geworden.

    Aber alles steht und fällt mit dem verfügbaren Compiler.



  • @Wutz sagte in Zeiger auf ein Element aus std::map zurückgeben:

    Warum glaubst du wohl, haben die Entwickler deines Amiga-OS Zeiger als API gewählt und bieten keine C++ API an? Eben weil sie selbst solchen Wrapping-Aufwand gescheut haben - und lieber nativ bleiben

    Falsch. Die Frage hat sich gar nicht gestellt, einfach weil Amiga-OS älter als C++ ist. Davon abgesehen gibt es noch mehr Gründe, darunter auch echte die kein Strohmann sind, gegen den Einsatz von C++ in OS Schnittstellen.

    Vielleicht findest du ja einen Vollprofi in deiner Nähe den du mal fragen kannst, vielleicht erklärt er es dir.


Anmelden zum Antworten