Wie lange hat es gedauert bis ihr alle Aspekte von C++ verinnerlicht hattet?



  • Es ist wahr.



  • Decimad schrieb:

    Dass einem immer gleich schlechtes Design vorgeworfen werden muss 😉

    Das war nicht als Vorwurf gemeint. Es ist einfach nur meiner Erfahrung nach so, dass man vergleichsweise sehr selten tatsächlich Fälle von Shared Ownership hat. In der Regel gibt es wohl meistens einfach einen Besitzer und einige andere Objekte, die dann mit dem Objekt unabhängig von dessen Lebensdauer arbeiten, oft überhaupt nur über ein Interface...

    Kann natürlich sein, dass Reference Counting bei dir tatsächlich in allen Fällen Sinn macht. Ich persönlich halt es eben einfach so, dass ich Shared Ownership als potentielles Symptom dafür sehe, dass ich die Abhängigkeiten in meinem Design noch nicht ganz verstanden habe. Und bisher konnte ich praktisch alle Fälle von Shared Ownership (bei mir meist früher im Umgang mit COM Objekten einfach im Vorbeigehen vorsichtshalber eingebaut) durch Refactoring in etwas Besseres transformieren. Der einzige potentielle Fall von Shared Ownership, an den ich mich aus den letzten Jahren so erinnern kann, wäre der Glyph Cache in meinem Text Renderer. Und auch da versuche ich, noch eine bessere Lösung zu finden..



  • dot schrieb:

    Aber diese Dinge ließen sich davor auch über Libraries beherrschen. [...] Aber rvalue references erlauben mir, Dinge auszudrücken, die ich zuvor rein prinzipiell, egal wie hoch auch der Aufwand, nicht ausdrücken konnte...

    Kennst du Boost.Move? Diese Bibliothek versucht RValue-Referenzen unter C++03 zu emulieren. Boost beweist jedes Mal wieder aufs Neue, wie mächtig C++ ist, das ist schon fast bedenklich... 😮

    Die Idee der Move-Semantik existierte ohnehin schon vor C++11, nur halt nicht direkt in die Sprache integriert. Siehe std::auto_ptr .

    dot schrieb:

    Z.B. im Umgang mit OpenGL haben sich rvalue references für mich in der Praxis als unbezahlbar herausgestellt.

    Klingt interessant, kannst du das erläutern?



  • Nexus schrieb:

    Die Idee der Move-Semantik existierte ohnehin schon vor C++11, nur halt nicht direkt in die Sprache integriert. Siehe std::auto_ptr .

    In der Tat, auto_ptr ist aber eben broken und mit C++11 nicht umsonst deprecated, weil Move-Semantik sich vor rvalue References eben nicht so richtig toll umsetzen ließ...

    Nexus schrieb:

    dot schrieb:

    Z.B. im Umgang mit OpenGL haben sich rvalue references für mich in der Praxis als unbezahlbar herausgestellt.

    Klingt interessant, kannst du das erläutern?

    Naja, da gibt es wohl nicht viel zu erläutern, sämtliche OpenGL Names (Handles) mappen praktisch direkt auf unique_ptr Style RAII. Vor C++11 fand ich es relativ anstregend, RAII auf OpenGL Objekte anzuwenden. Wenn beispielsweise ein Texture Render Target resized werden sollte, gab es keinen einfachen Weg, einer vorhandenen GL::Texture2D einfach eine neue zuzuweisen. Natürlich kann man in OpenGL einfach das Texture Objekt hinter dem Name ersetzen, aber das find ich eher unsauber. Move-Semantik löst dieses Problem. Oder eine Funktion, die ein Bild aus einer Datei lädt, konnte auch nicht so einfach eine GL::Texture2D returnen. Natürlich konnte man einen entsprechenden Texture2D Konstruktor machen, was ich aber wieder als unbedfriedigende Lösung emfpinde, denn die Texture2D sollte sich eben nur um die Verwaltung der Ressource kümmern und nicht auch noch um das Laden der Daten aus allen möglichen Quellen...



  • dot schrieb:

    In der Regel gibt es wohl meistens einfach einen Besitzer und einige andere Objekte, die dann mit dem Objekt unabhängig von dessen Lebensdauer arbeiten, oft überhaupt nur über ein Interface...

    Wie handhabst du Ressourcen wie Bilder/Sounds, die an mehreren Orten benötigt werden?

    Es liegt nahe, wenn ein zentraler Manager die Ressourcen besitzt und Clients diese referenzieren. Aber wie stellst du z.B. sicher, dass nicht eine Ressource entladen wird, wenn sie noch in Gebrauch ist? Oder dass unbenutzte Ressourcen automatisch freigegeben werden? Wenn dazu eine komplexe Logik mit Callbacks und Überwachung der Lebenszeit notwendig ist, könnte man auch direkt shared_ptr nehmen...

    dot schrieb:

    In der Tat, auto_ptr ist aber eben broken und mit C++11 nicht umsonst deprecated...

    Ja, aber das sind technische Mühseligkeiten und Pitfalls. Du sprachst von einer prinzipiellen Unmöglichkeit 😉



  • Sollte man in C++11 überhaupt noch per Referenz übergeben? z.B bei solchen Funktionen:

    std::string get_first(std::vector<std::string> const& vec) {
      return vec.front();
    }
    

    Wenn man per Referenz übergibt, braucht man gar keine Kopie, egal ob der Parameter ein RValue oder ein LValue ist.

    std::string get_first(std::vector<std::string> vec) {
      return vec.front();
    }
    

    Hier müsste der Vektor doch kopiert werden, wenn der Parameter ein LValue ist, oder? z.B wenn man die Funktion so verwendet?

    std::vector<std::string> vec;
    vec.push_back("Hello");
    std::string first = get_first(vec);
    // Do other stuff with vector
    

    Sollte man in so einem Fall also per const Referenz übergeben, oder optimieren das die Compiler?



  • Ja, Übergabe als LValue-Referenz ist nach wie vor sinnvoll. Nur kannst du in C++11 eben RValues besser behandeln.



  • *hust Ähm, Moderator? Wäre es möglich die MoveTheRValue-Diskussion, die zweifellos sehr interessant ist, abzusplitten?



  • Nexus schrieb:

    dot schrieb:

    In der Regel gibt es wohl meistens einfach einen Besitzer und einige andere Objekte, die dann mit dem Objekt unabhängig von dessen Lebensdauer arbeiten, oft überhaupt nur über ein Interface...

    Wie handhabst du Ressourcen wie Bilder/Sounds, die an mehreren Orten benötigt werden?

    Es liegt nahe, wenn ein zentraler Manager die Ressourcen besitzt und Clients diese referenzieren. Aber wie stellst du z.B. sicher, dass nicht eine Ressource entladen wird, wenn sie noch in Gebrauch ist? Oder dass unbenutzte Ressourcen automatisch freigegeben werden? Wenn dazu eine komplexe Logik mit Callbacks und Überwachung der Lebenszeit notwendig ist, könnte man auch direkt shared_ptr nehmen...

    Ich sagte nicht, dass Shared Ownership niemals Sinn macht, ich hab ja auch selbst ein Beispiel gegeben, wann es Sinn machen könnte, das dem Deinen auch gar nicht so unähnlich ist (Glyphen, Bilder, dlls...steckt ja im Prinzip in allen Fällen das gleiche Problem dahinter). Ich stimme dir also natürlich zu, dass es durchaus Fälle von Shared Ownership gibt. Aber nur weil es eben Beispiele gibt, wo es Sinn macht, heißt das noch lange nicht, dass es meistens Sinn macht. Was der Regelfall ist, hängt natürlich teilweise davon ab, in welcher Domäne man sich bewegt. Aber ich denke, dass Shared Ownership doch fast immer eher die Ausnahme als die Regel ist. Und einfach prinzipiell überall shared_ptr zu verwenden ist auf jeden Fall eine ganz schlechte Idee und zeugt nicht von besonders tiefgehendem (bzw. überhaupt irgendeinem) Verständnis der Problematik. Was ich eben eigentlich argumentieren wollte ist, dass, wenn man denn eine Guideline haben will, unique_ptr (Ownership Transfer) eher der Default sein sollte während shared_ptr (Shared Ownership) eher für Spezialfälle reserviert ist...

    Nexus schrieb:

    dot schrieb:

    In der Tat, auto_ptr ist aber eben broken und mit C++11 nicht umsonst deprecated...

    Ja, aber das sind technische Mühseligkeiten und Pitfalls. Du sprachst von einer prinzipiellen Unmöglichkeit 😉

    Ich hab mir ja schon beim Verfassen des entsprechenden Postings gedacht, dass irgendwer was gegen meinen Wortlaut haben wird, aber gut, um das klarzustellen, einigen wird uns auf: Es war prinzipiell unmöglich, Ownership Transfer sauber umzusetzen!?

    Btw: Gab es für Perfect Forwarding auch eine prä C++11 Lösung? 😉



  • dot schrieb:

    Ich sagte nicht, dass Shared Ownership niemals Sinn macht

    Hab ich auch nicht so verstanden, keine Sorge. Ich bin selbst der Meinung, dass shared_ptr oft zu leichtsinnig eingesetzt wird und sich Leute der Kosten nicht bewusst sind. Aber hättest du für so ein Ressourcen-System auch shared_ptr verwendet, oder wie hättest du das gelöst?

    dot schrieb:

    Ich hab mir ja schon beim Verfassen des entsprechenden Postings gedacht, dass irgendwer was gegen meinen Wortlaut haben wird

    Mit der extremen Formulierung hast du es geradezu provoziert :p

    Nein, ich wollte nur darauf hinweisen, dass Move-Semantik nicht etwas ist, das mit C++11 vom Himmel gefallen ist. Aber zum ersten Mal kann man es jetzt sauber umsetzen.

    Butterbrot schrieb:

    *hust Ähm, Moderator? Wäre es möglich die MoveTheRValue-Diskussion, die zweifellos sehr interessant ist, abzusplitten?

    Ja, wäre eine gute Idee.



  • Um auf's Thema zurückzukommen:
    Ich hatte ca. 42 Wochen gebraucht, bis ich Guru in allen Belangen war und endlich an die Öffentlichkeit treten wollte. Dann kam dieser eine versoffene Abend und seither laufe ich meiner Form hinterher!



  • Nexus schrieb:

    Aber hättest du für so ein Ressourcen-System auch shared_ptr verwendet, oder wie hättest du das gelöst?

    Jap, wenn shared_ptr direkt eine einfache Lösung für das konkrete Problem bieten würde, hätte ich es wohl einfach verwendet. In meinem Fall mit dem Glyph Cache dachte ich darüber nach, erstmal selbst einfach eine Art Reference Counting zu implementieren (shared_ptr wäre dort nicht wirklich anwendbar). Mit dem letzten Refactoring ist es nun allerdings nichtmehr notwendig, die Glyphen im Cache zu behalten, solange sie noch irgendwo verwendet werden und damit eröffnet sich die Möglichkeit, das Ding in einen richtigen Cache zu verwandeln und einfach einen LRU o.ä. Algorithmus zu verwenden. Imo wäre das in dem Fall eine bessere Lösung, da all die gegenseitigen Referenzierungen zwischen Dingen, die Glyphen verwenden und den Glyphen selbst verschwinden. Und bei einer potentiell großen Anzahl an Buchstaben, ist das wohl erstrebenswert. In deinem Beispiel mit den Bildern ist shared_ptr allerdings natürlich eine attraktive Lösung. Die Frage ist allerdings wieder, wie viele dieser Bilder nun tatsächlich von mehr als einem Objekt verwendet werden und ob ein geteiltes Bild nicht vielleicht einfach dort gehalten werden kann, wo auch die Objekte, die es verwenden, gehalten werden oder ob nicht vielleicht zumindest auf anderem Wege einfach die gleiche Lebensdauer garantiert werden kann, ohne jetzt direkt jedem Objekt Besitz über das Bild zu geben. Ich denke da jetzt z.B. wieder an Texturen. Meistens wird eben ein bestimmes Modell eine bestimmte Textur verwenden. Der Fall, dass verschiedene Modelle die gleiche Textur verwenden, ist natürlich durchaus vorstellbar, aber sicherlich nicht unbedingt der Regelfall. Und in dem Fall wird es wohl nicht unwahrscheinlich sein, dass zwischen diesen Modellen auch ein logischer Zusammenhang besteht und diese daher auch irgendwo an gemeinsamer Stelle verwaltet werden, womit es dann aber vielleicht möglich wäre, die Textur zusammen mit den Modellen zu halten und einfach eine Referenz an die Modelle zu übergeben. Und schon ist die Shared Ownership wieder aufgelöst...

    Nexus schrieb:

    dot schrieb:

    Ich hab mir ja schon beim Verfassen des entsprechenden Postings gedacht, dass irgendwer was gegen meinen Wortlaut haben wird

    Mit der extremen Formulierung hast du es geradezu provoziert :p

    Nein, ich wollte nur darauf hinweisen, dass Move-Semantik nicht etwas ist, das mit C++11 vom Himmel gefallen ist. Aber zum ersten Mal kann man es jetzt sauber umsetzen.

    Nun, da stimmen wir natürlich in unserer Meinung völlig überein, aber zugegeben, ich hab es etwas provokant Formuliert... 😉



  • Habe ich was verpasst? Macht shared_ptr kein ref counting? Und warum wird unique_ptr ins Spiel gebracht, wenn es um shared ownership geht. Und was hat das mit move-Semantik zu tun? Ging vorher auch schon, musst man halt selbst machen. Warum sollten auf einmal Referenzen out werden? Welche alten Prinzipien werden jetzt ungueltig?



  • Um zum Thema zurückzukommen:
    allein die wichtigsten Fakten über C++ zu lernen, dürfte irgendwas zwiaschen 3 und 12 Monaten dauern, bis man alle Einzelheiten und Feinheiten kennt, deutlich länger (Der Standard ist groß...).
    Die ganzen Implikationen zu lernen, d.h. wie man mit der Sprache umgeht, was Sinn macht und was nicht, dauert noch sehr viel länger, auch je nachdem wie viele der Sprachelemente man benutzt. Ich würde mich z.B. durchaus schon als Fortgeschrittener bis Profi sehen, habe aber auch schon 2004 mit C++ angefangen. 5 Jahre hats aber sicherlich gedauert, bis ich mich so weit gesehen habe. Das heißt aber nicht, dass es nicht mehr zu lernen gibt, ich habe z.B. noch einige Defizite im neuen Standard, auch in vielen feinen Details des alten Standards, ich kann mit dingen wie Mehrfachvererbung und virtueller Vererbung einfach nicht umgehen. Das Konzept und die Probleme verstehe ich (denke ich), habe aber keine Erfahrung damit. Bis ich den neuen Standard weitgehend intus habe steht der nächste schon wieder vor der Tür - ich denke man kann guten Gewissens behaupten, dass man wie in so vielen Bereichen des Lebens einfach nie auslernt.



  • Danke, sehr gut beschrieben und endlich wieder Topic^^



  • pumuckl schrieb:

    ...bis man alle Einzelheiten und Feinheiten kennt, deutlich länger...

    Wenn dies den überhaupt je geschieht. Es gibt Bereiche die einfach für viele Anwendungen unnötig, oder nur sehr selten relevant sind.

    Ich habe jetzt mal genauer nachgeschaut... Angefangen mit C++ habe ich etwa Ende 1996. Ich kenne das was für meine tägliche Arbeit nötig und möglich ist. So habe ich mich aus mehreren Gründen noch nicht wirklich mit vielen Themen zu C++11 und speziellen Teilen (z.B. Template Metaprogrammierung) beschäftigt - da ich es auch gar nicht einsetzen könnte, selbst wenn ich wollte. Es war schon schwierig genug einiges vom Standard in das Projekt einzubauen (hier wurde vorher vieles händisch gemacht).

    Daher: Hängt euch nicht mit "allen Aspekten" auf. Solide Kenntnisse kann man innerhalb eines Jahres erwerben, wobei mindestens noch ein paar Jahre allgemeine Projekterfahrungen nötig sind um wirklich sinnvoll programmieren zu können (Vieles lernt man erst durch Anwendung, oder durch Rückmeldung von anderen) - Erfahrung sollte man nie unterschätzen. Ebenso wird man erst im laufe einiger Zeit abschätzen können was wirklich für die Projekte sinnvoll ist.

    C++ vollständig zu beherrschen bringt meist in der Praxis nicht wirklich so viel - so lange man solide Kenntnisse der wesentlichen Bereiche beherrscht reicht dies.



  • Obwohl ich nicht den kompletten Thread gelesen hab, und deshalb auch nicht weiß, ob sowas in der Art nicht schon geschrieben wurde, möchte ich trotzdem gerne mitspielen. 😉
    Analog zur Frage "Wie lange hat es gedauert bis ihr alle Aspekte von C++ verinnerlicht hattet?" gibt es im einem Akrobatik-Forum, in dem ich viel unterwegs bin, öfters mal fragen wie "Wie lange habt ihr gebraucht bis ihr einen guten Rückwärtssalto konntet?". Die Standard-Antwort auf sowas ist dann:

    'Naja, kommt drauf an, was du unter "gut" verstehst. Da hat jeder andere Ansprüche. Außerdem kommt jeder mit anderen athletischen Voraussetzungen daher. Manche haben auch koordinative Vorteile, weil sie vorher schon mal etwas ähnliches gemacht haben, und nicht jeder Steckt gleich viel Energie ins Training. Weil Leute also aus mehreren Gründen verschieden schnell lernen, kannst du also aus den Posts, die eventuell als Antwort auf deine Frage kommen werden, kaum ableiten, wie lange "es" bei dir dauern wird.'

    Ich hab das Gefühl, dass sich das fast komplett auf C++ übertragen lässt. 🙂



  • Dobi schrieb:

    Ich hab das Gefühl, dass sich das fast komplett auf C++ übertragen lässt. 🙂

    Definitiv, klasse Beitrag!



  • Habe gerade in Herb Sutters Blog auch etwas passendes zum Thema gelesen:

    I just got back from teaching a class, and I’m always amazed at the breadth and diversity of C++ developers. As Bjarne Stroustrup famously says: “No one knows ‘what most C++ developers do.’”

    In particular, I’m surprised at how strongly some people feel about certain features, such as refactoring or safety or raw performance or exhaustive conformance, that don’t matter much at all to other people, ...



  • nn schrieb:

    Habe gerade in Herb Sutters Blog auch etwas passendes zum Thema gelesen:

    Hat eigentlich mit dem Thema wenig zu tun. Hier gehts um die Sprache C++ und wie man damit entwickelt (bzw. das Entwickeln lernt). In dem Blogpost (und dem Zitat) gehts um was ganz anderes, nämlich um Features der IDEs/Compiler, die Leute nutzen, sich wünschen und erwarten. Das ist etwas was mit der Sprache erstmal wenig zu tun hat.
    Was eher in die Richtugn geht: http://www.meetingcpp.com/index.php/newsreader/items/islands-of-c.html - hier gehts um die verschiedenen "Geschmacksrichtungen" und Subsets von C++, die verschiedene C++-Entwickler benutzen. Nennt sich alles C++, aber die Lernkurven und damit die Zeit, die man benötigt, um "es" zu beherrschen, sind unterschiedlich.
    In dem Sinne eine weitere Antwort an den Fragesteller: nicht nur "verinnerlicht" ist wie schon in vorigen Beiträgen gesagt ein schwammiger und ungenauer Begriff, sondern auch "alle Aspekte von C++". Je nach Entwicklungsumgebungen sind verschiedene Bibliotheken und Bibliotheksteile mit dem verbunden, was der jeweilige Entwickler als "alle Aspekte" verstehen mag.


Anmelden zum Antworten