Benennung von "Accessors"


  • Administrator

    Nexus schrieb:

    Vielmehr habe ich grundsätzlich etwas gegen unnötig viel Code. Bei mir geht Einfachheit vor, sofern dadurch keine wesentlichen Nachteile entstehen. Und nicht selten sehe ich mit weniger Code auch schneller, was passiert (damit meine ich keine Abkürzungen, wobei es auch da sinnvolle gibt). Und hier ist es meiner Meinung nach so, dass die lokalen Variablen keinen wirklichen Vorteil bringen, daher lasse ich sie weg. Aber bei wirklich komplexen Ausdrücken mach ichs auch wie du. Bei mir ist halt die Grenze, wo ich durch die Auslagerung einen Gewinn sehe, etwas weiter entfernt als bei dir.

    Ich mag verschachtelte Funktionen nicht. Sowas empfinde ich als sehr mühsam zum Lesen. Daher sind für mich die zusätzlichen Variablen eine Vereinfachung des Codes. Ich verschachtle sogar nur sehr ungern die Properties aus C#.

    Nexus schrieb:

    Dravere schrieb:

    Nö. Es gibt nach meinem Wissen keine Vorschrift für den Kompiler, dass er diese Kopie durchführen muss.

    Doch, die gibt es. Kopien dürfen nur genau in zwei Situationen wegoptimiert werden: Bei temporären Objekten und Rückgabewerten von Funktionen.

    Standard, Kapitel, Absatz? Tut mir Leid, aber sonst kauf ich dir das nicht ab, denn das wäre mir ganz neu. Wieso sollte es verboten sein, unnötige Kopien ohne Nebeneffekte wegzuoptimieren?

    Nexus schrieb:

    Ja, so würde ichs auch tun. Ich habe auch kein Problem damit, bei grösseren Objekten eine Const-Referenz als Rückgabetyp zu verwenden. Aber ich habe schon anderes gehört...

    Ich bin mir nicht ganz sicher, ob du da mein Argument richtig verstanden hast. Es ging mir in erster Linie darum, wenn jemand keine "Const-Referenz" zurückgibt, dass man dann trotzdem die Variable als "Const-Referenz" empfangen kann:

    class Rectangle
    {
    public:
      Size getSize() const;
    };
    
    // ...
    Size const& size = client_rectangle.getSize();
    
    // mit size arbeiten.
    

    Nexus schrieb:

    Übrigens: Fang nicht auch noch an mit "konstanten Referenzen" :p

    Ja, ja, ich weiss. Deshalb habe ich es vor dem Komma noch so umständlich umschreiben und nach dem Komma keine Lust mehr gehabt. Sollen wir eine Abkürzung einführen? 😃
    RAKO - Referenz Auf Konstantes Objekt

    Nexus schrieb:

    Zu den Accessor -spezifischen Dingen: Ich hab mir da keine konkrete Implementierung gebastelt, das sind mehr ein paar Vorstellungen. Mit den impliziten Konvertierungen habe ich gemeint, dass sie dann erwünscht sind, wenn die Property von ausserhalb der Klasse benutzt wird (als Getter), und dann sollen sie immer in Kraft treten. Jedoch ist das manchmal schwierig:

    Ich habe jetzt mit dem explicit nicht unbedingt den Konvertierungsoperator gemeint, sondern eher einen Konstruktor. Wenn man nämlich den Wert in Accessor speichert, dann wäre es sinnvoll eine Initialisierung anzubieten. Dieser Konstruktor müsste man zwingend auf explicit setzen, da sonst andere Unschönheiten passieren. Ich würde sowieso alle Konstruktoren in der Klasse Accessor auf explicit setzen. Man wird darauf ja auch kaum anders als explizit zugreifen.

    Grüssli



  • Dravere schrieb:

    Standard, Kapitel, Absatz? Tut mir Leid, aber sonst kauf ich dir das nicht ab, denn das wäre mir ganz neu.

    Man kann immer dazulernen. Aber weil du mir nicht glaubst:

    12.8/15 Copying class objects schrieb:

    When certain criteria are met, an implementation is allowed to omit the copy construction of a class object, even if the copy constructor and/or destructor for the object have side effects. In such cases, the implementation treats the source and target of the omitted copy operation as simply two different ways of referring to the same object, and the destruction of that object occurs at the later of the times when the two objects would have been destroyed without the optimization.111) This elision of copy operations is permitted in the following circumstances (which may be combined to eliminate multiple copies):
    — in a return statement in a function with a class return type, when the expression is the name of a non-volatile automatic object with the same cv-unqualified type as the function return type, the copy operation can be omitted by constructing the automatic object directly into the function’s return value
    — when a temporary class object that has not been bound to a reference (12.2) would be copied to a class object with the same cv-unqualified type, the copy operation can be omitted by constructing the temporary object directly into the target of the omitted copy

    Dravere schrieb:

    Wieso sollte es verboten sein, unnötige Kopien ohne Nebeneffekte wegzuoptimieren?

    Weil sie relevante Nebeneffekte haben könnten.



  • Nexus schrieb:

    12.8/15 Copying class objects schrieb:

    When certain criteria are met, an implementation is allowed to omit the copy construction of a class object, even if the copy constructor and/or destructor for the object have side effects.

    Und wo steht da, dass es verboten ist, den Kopierkonstruktor auszulassen, wenn er keine Seiteneffekte hat?

    Eine Klasse ist gut, wenn sie den Kopierkonstruktor vom Kompiler bekommen hat und nur aus pod-Typen oder guten Klassen besteht (Achtung: Rekursion). Ist es verboten, die Kopien von guten Klassen zu wegoptimieren?



  • dazulerner schrieb:

    Und wo steht da, dass es verboten ist, den Kopierkonstruktor auszulassen, wenn er keine Seiteneffekte hat?

    Da steht, die Kopie darf nur weggelassen werden, wenn die beiden Kriterien erfüllt sind. "Nur", weil Kopierkonstruktoren normalerweise nicht wegoptimiert werden und hierfür extra eine Sonderregel im C++-Standard eingerichtet worden ist.

    Dem entnehme ich, dass die Optimierung in den anderen Fällen streng genommen nicht erlaubt ist, auch wenn keine Seiteneffekte vorhanden sind. Dies ist zumindest meine Auslegung des Paragraphen. Wie Compiler das umsetzen, ist dann ohnehin wieder ein anderes Thema.



  • @Dravere, ohne wirklich richtig zu cheaten (weil es sozusagen wirklich stimmt) könnte man den Byteoffset des Member-Accessors mitgeben, dann kann der sich aus seinem eigenen this-Zeiger den des umliegenden Objekts errechnen. Fällt mir gerade so ein. Ist natürlich unschön, aber sieht nachher niemand mehr^^
    Edit: Vielleicht würde ein guter Compiler dann ach die Ausdrücke x+offset-offset erkennen, die da dann immer auftauchen und sie gleich ganz eliminieren...



  • Nexus schrieb:

    Zu den Accessor -spezifischen Dingen: Ich hab mir da keine konkrete Implementierung gebastelt, das sind mehr ein paar Vorstellungen. Mit den impliziten Konvertierungen habe ich gemeint, dass sie dann erwünscht sind, wenn die Property von ausserhalb der Klasse benutzt wird (als Getter), und dann sollen sie immer in Kraft treten. Jedoch ist das manchmal schwierig:

    template <typename T>
    void DoSomething(T t);
    
    DoSomething(obj.Size);
    // Da der erste Parameter ein Template-Typ-Parameter ist, wird nie eine
    // Konvertierung vorgenommen. Man übergibt also das Proxy statt der Grösse
    

    Da hast du natürlich recht, das würde zu vielen unnötigen Template-Instanziierungen führen. Grumpf.
    Edit: Snip. Stimmt natürlich gar nicht, es kann ja in der Form keine freien Instanzen von den Accessor-Objekten geben, aber dein Beispiel gilt natürlich analog für Referenzen.



  • Nexus schrieb:

    Dem entnehme ich, dass die Optimierung in den anderen Fällen streng genommen nicht erlaubt ist, auch wenn keine Seiteneffekte vorhanden sind.

    Doch, Optimierungen sind immer erlaubt. Die einzige Forderung ist, dass das Programm sich nach außen hin so verhält, wie es spezifiziert ist. Die Sonderregel mit dem Kopierkonstruktor besagt, dass in gewissen, genau festgelegten Fällen Kopierkonstruktoren wegoptimiert werden dürfen, selbst wenn sich dadurch Änderungen im beobachtbaren Verhalten ergeben.



  • So macht das natürlich Sinn. Danke für die Erklärung!


  • Administrator

    Decimad schrieb:

    @Dravere, ohne wirklich richtig zu cheaten (weil es sozusagen wirklich stimmt) könnte man den Byteoffset des Member-Accessors mitgeben, dann kann der sich aus seinem eigenen this-Zeiger den des umliegenden Objekts errechnen. Fällt mir gerade so ein. Ist natürlich unschön, aber sieht nachher niemand mehr^^
    Edit: Vielleicht würde ein guter Compiler dann ach die Ausdrücke x+offset-offset erkennen, die da dann immer auftauchen und sie gleich ganz eliminieren...

    Meinst du dies jetzt als Lösung wegen dem Problem mit this ? Dann ist deine Idee alles andere als sinnvoll. Das Programm greift schliesslich selber bereits genau so drauf zu. Da ändert es nichts, ob man nun selber über den Offset geht oder der Kompiler dies über this für einem ausrechnet. Es bleibt undefiniertes Verhalten.
    Eine Möglichkeit, was passieren könnte, ist, dass du über den Offset die Speicherstelle beschreibst, da die Klasse aber noch nicht vollständig initialisiert ist, wird der Speicherbereich dann vom eigentlichen Konstruktor erneut überschrieben und deine Initialisierung geht flöte.

    Definitiv keine gute Idee ...

    @Nexus,
    Deswegen können eben C und C++ Kompiler so aggressiv optimieren, weil es grundsätzlich keine Verbote gibt. Und die Regel ist eben nur eine Hilfe für zusätzliche Optimierungen. C++ ist voll darauf ausgelegt, dass optimiert werden kann ohne Ende.

    Grüssli



  • @Dravere, du hast mich offenbar missverstanden. Ich wollte damit nicht das "zu frühe" Verwenden von "this" umgehen, sondern den Speicherplatz für this_ im Accessor einsparen (womit sich auch komplett die zu frühe Benutzung erübrigt, weil der Accessor nicht mehr die Laufzeit-Hilfe der beinhaltenden Klasse benötigt).



  • Eigentlich war mir diese Grundsatzregel mit dem Optimieren bekannt, doch da der Standard sich im Bezug auf Kopierkonstruktoren so explizit ausdrückte, hielt ich das für bindend. Von der Grundsatzregel habe ich hingegen nie was Offizielles gelesen...

    Abgesehen davon weiss ich nicht, wie offensiv heutige Compiler sind. Aber auf die "guten" Klassen von dazulerner wird es wohl schon zutreffen. Dennoch wäre ich vorsichtig mit dem Spekulieren auf Kopier-Optimierungen, sobald der Einfluss auf die Performance wesentlich wird.


  • Administrator

    Decimad schrieb:

    @Dravere, du hast mich offenbar missverstanden. Ich wollte damit nicht das "zu frühe" Verwenden von "this" umgehen, sondern den Speicherplatz für this_ im Accessor einsparen (womit sich auch komplett die zu frühe Benutzung erübrigt, weil der Accessor nicht mehr die Laufzeit-Hilfe der beinhaltenden Klasse benötigt).

    Kannst du mir das zeigen, wie du das machen willst?
    Ich zweifle sehr, dass du dies definiert hinbekommst.

    Nexus schrieb:

    Dennoch wäre ich vorsichtig mit dem Spekulieren auf Kopier-Optimierungen, sobald der Einfluss auf die Performance wesentlich wird.

    Da stimme ich dir zu.

    Grüssli



  • Leider gar nicht, aber im Prinzip wüsste der Compiler es ja, schade nur, dass er es uns für nicht POD-Klassen nicht sagen mag.
    Also bei konformer C++-Benutzung ist man auf diesen this_-Zeiger angewiesen.
    Aber ich meine in Boost sogar schonmal solche nicht-Standardkonformen Pro-Compiler-Optimierungen gesehen zu haben.



  • Nexus schrieb:

    Eigentlich war mir diese Grundsatzregel mit dem Optimieren bekannt, doch da der Standard sich im Bezug auf Kopierkonstruktoren so explizit ausdrückte, hielt ich das für bindend. Von der Grundsatzregel habe ich hingegen nie was Offizielles gelesen...

    1.9§5:
    "A conforming implementation executing a well-formed program shall produce the same observable behavior as one of the possible execution sequences of the corresponding instance of the abstract machine with the same program and the same input. [...]"

    Fußnote: "This provision is sometimes called the «as-if» rule, because an implementation is free to disregard any requirement of this International Standard as long as the result is as if the requirement had been obeyed, as far as can be determined from the observable behavior of the program. [...]"



  • Ah, alles klar. Danke. 🙂


Anmelden zum Antworten