Konstante Parameter



  • Was mir jetzt zu const und Compileroptimierung einfällt ist, dass es doch der Compiler mit Sicherheit merkt ob in einer Funktion/Methode ein Wert verändert wird und dem entsprechend optimiert. Also nimmt das const dann doch mehr die Rolle des Überschreibschutzes ein als die Rolle einer Geschwindigkeitsoptimierung, jedenfalls bei elementaren Datentypen.



  • blue-tec schrieb:

    Was mir jetzt zu const und Compileroptimierung einfällt ist, dass es doch der Compiler mit Sicherheit merkt ob in einer Funktion/Methode ein Wert verändert wird und dem entsprechend optimiert.

    Wenn der Compiler weiß, das eine Variable innerhalb eines Kontext unveränderlich ist, kann er Annahmen treffen die, die Performace theoretisch beeinflussen können (unabhängig von Compilezeitkonstanten).

    Ob das in der Praxis aber eine Auswirkung hat, bleib dahin gestellt.



  • blue-tec schrieb:

    Was mir jetzt zu const und Compileroptimierung einfällt ist, dass es doch der Compiler mit Sicherheit merkt ob in einer Funktion/Methode ein Wert verändert wird und dem entsprechend optimiert. Also nimmt das const dann doch mehr die Rolle des Überschreibschutzes ein als die Rolle einer Geschwindigkeitsoptimierung, jedenfalls bei elementaren Datentypen.

    Wie du vom ersten Satz auf den zweiten schliesst, ist mir nicht ganz klar. Das klingt für mich eher widersprüchlich.

    Wie genau soll der Compiler im allgemeinen Fall bei const optimieren? Bei Referenzen und Zeigern auf const weiss er ja nicht, ob das Originalobjekt tatsächlich const -qualifiziert ist. const_cast ist in einem gewissen Rahmen ebenfalls erlaubt.

    Jedenfalls ist es ein Irrglaube, dass const die Performance entscheidend verbessert. Es kann in vereinzelten Fällen vorkommen, aber dass nicht andere Programmteile viel zeitkritischer sind, kommt ziemlich selten vor.


  • Mod

    Um mal zu erklären, warum const selten Optimierung erlaubt, die ohne const nicht da wäre:
    a) mutable : Die Möglichkeit, dass eine Klasse mutable Member enthält, lässt keine Möglichkeit zu aus, bloß aus const zu folgern, dass tatsächlich sich nichts verändert.
    b) volatile : Siehe oben
    c) Wenn sich tatsächlich nichts ändert, sieht das der Compiler direkt am erzeugten Maschinencode, egal ob im ursprünglichen Code einmal const stand oder nicht und kann entsprechend optimieren (Ausnahme: volatile-Member, aber volatile soll ja gerade solche Optimierungen verhindern).

    http://www.informit.com/guides/content.aspx?g=cplusplus&seqNum=372

    edit: Da war Nexus schneller als ich. Ob er wohl const-qualifiziert ist? 😃



  • Nexus schrieb:

    blue-tec schrieb:

    Was mir jetzt zu const und Compileroptimierung einfällt ist, dass es doch der Compiler mit Sicherheit merkt ob in einer Funktion/Methode ein Wert verändert wird und dem entsprechend optimiert. Also nimmt das const dann doch mehr die Rolle des Überschreibschutzes ein als die Rolle einer Geschwindigkeitsoptimierung, jedenfalls bei elementaren Datentypen.

    Wie du vom ersten Satz auf den zweiten schliesst, ist mir nicht ganz klar. Das klingt für mich eher widersprüchlich.

    Wie genau soll der Compiler im allgemeinen Fall bei const optimieren? Bei Referenzen und Zeigern auf const weiss er ja nicht, ob das Originalobjekt tatsächlich const -qualifiziert ist. const_cast ist in einem gewissen Rahmen ebenfalls erlaubt.

    Jedenfalls ist es ein Irrglaube, dass const die Performance entscheidend verbessert. Es kann in vereinzelten Fällen vorkommen, aber dass nicht andere Programmteile viel zeitkritischer sind, kommt ziemlich selten vor.

    Ich wollte damit ausdrücken dass const nicht zur Steigerung der Performance beträgt sondern eher als ein Schutz gegen ungewolltes Überschreiben da ist.

    Ist das bei Objekten aus selbst erstellten Datentypen dann anders?


  • Mod

    blue-tec schrieb:

    Ich wollte damit ausdrücken dass const nicht zur Steigerung der Performance beträgt sondern eher als ein Schutz gegen ungewolltes Überschreiben da ist.

    Ist das bei Objekten aus selbst erstellten Datentypen dann anders?

    Eben nicht. Das was du beschreibst ist sogar die eigentliche Aufgabe von const. Eventuelle Performancevorteile die vielleicht unter gewissen Umständen auftauchen könnten, sind ein seltener Nebeneffekt.



  • JnZn558 schrieb:

    ist es eigentlich sinnvoll kontante parameter zu verwenden. z.B.

    int test( const int a, const int b, const int* c ){
       return a + b + *c;
    }
    

    oder lieber const float* const c??

    Hab nicht alle Argumente gelesen, aber ich nehme auch bei ints und floats die ich als copy-parameter bekomme consts. Das hat keinen Performancegrund oder sonstige Gründen sondern nur einen: Fehlervermeidung.
    Wie schnell passiert sowas:

    void foo(int a)
    {
      if ( a = 1 )
      //....
    }
    

    Klar, es ist vermeidbar etc. Trotzdem habe ich es mir angewöhnt aufgrund genau solcher Fehler und bleibe dabei. Lieber sofort einen Compilerfehler bei sowas als evtl stundenlange Fehlersuche. Ich sehe keinen deutlich messbaren Unterschied zwischen const und nicht const bei dieser Art von Parameter.
    rya.

    ps.:
    Bei Klassen und Referenzen spielen natürlich andere Gründe noch mit eine Rolle wie eben Performance, weil eine Referenz von einer 3-4 MB großen liste schneller übergeben ist als eine Kopie etc.



  • scorcher24@public.pc schrieb:

    Hab nicht alle Argumente gelesen, aber ich nehme auch bei ints und floats die ich als copy-parameter bekomme consts. Das hat keinen Performancegrund oder sonstige Gründen sondern nur einen: Fehlervermeidung.
    Wie schnell passiert sowas:

    Das ist okay, solange du in der Schnittstelle (Deklaration im Header) das const weglässt. Dort hat es nämlich definitiv nichts zu suchen.



  • Warum nicht, wenn ich fragen darf?



  • blue-tec schrieb:

    Warum nicht, wenn ich fragen darf?

    Weil es sich um ein Implementierungsdetail handelt.

    Der Aufrufer hat rein gar keinen Nutzen davon, wenn er weiss, ob die Kopie von der Funktion verändert wird oder nicht.



  • blue-tec schrieb:

    Warum nicht, wenn ich fragen darf?

    Grundsätzlich bin ich ein starker Verfechter von const-correctness, aber unnötige const gehören nicht dazu. Man sollte man eine Schnittstelle nur mit "Nutzwert" füllen, und nicht mit unnötigen Code aufblähen.



  • Ich verstehe...da fällt mir noch eine Frage ein wenn es um die Deklaration geht. Ich habe schon einige Sourcecodes gesehen in dem auch nicht die Bezeichner bei den Methodenargumenten mit angegeben werden sondern nur die Datentypen. Was haltet ihr davon?



  • blue-tec schrieb:

    Ich habe schon einige Sourcecodes gesehen in dem auch nicht die Bezeichner bei den Methodenargumenten mit angegeben werden sondern nur die Datentypen. Was haltet ihr davon?

    Wenig. Der Name der Parameter ist wichtig – ohne ihn ist es schwierig, die Aufgabe der Variable zu erkennen.

    Besonders wenn man automatische Dokumentationstools wie Doxygen verwendet, ist der Header ziemlich wichtig. Aber auch sonst kann er dem Benutzer oft einen guten Überblick verschaffen. Es kann natürlich sein, dass man eine komplett separate Dokumentation hat, wie bei Boost. Dann ist es weniger tragisch, wenn im eigentlichen Header die Parameternamen fehlen (wobei diese auch oft der IDE als Vervollständigung dienen können).

    Ich würde Parameternamen im Header grundsätzlich immer hinschreiben, du verlierst ja nichts. Ausser natürlich bei offensichtlich nutzlosen Parametern wie bei operator++(int) . Wenn sie in der Implementierung nicht benötigt werden, kannst du die Funktionsdefinition immer noch ohne Parameternamen hinschreiben.

    Edit: "nutzlose Funktionen" durch "nutzlose Parameter" ersetzt 🙂



  • blue-tec schrieb:

    Ich habe schon einige Sourcecodes gesehen in dem auch nicht die Bezeichner bei den Methodenargumenten mit angegeben werden sondern nur die Datentypen. Was haltet ihr davon?

    Ich bin der Meinung von Nexus, zumal man gegen die Schnittstelle und nicht die Implementierung programmieren sollte - und jeder Blick den man zwangsweise zum Verstehen der Schnittstelle in den Source werfen muss, widerspricht diesem Ansatz.

    Für mich dient die Deklaration der Dokumentation: An dieser sollte man die Schnittstelle verstehen können.



  • Das klingt auch alles logisch. Wie verstecke ich dann aber am besten meinem privaten Membervariabeln, da diese ja von der Logik her zwar auch deklariert werden müssen aber für die Schnittstellen, die der Kunde dann sehen soll, unnötiger Ballast sind?





  • Hmm ja, ich hatte gehofft da gibt es was anderes außer die Members auszulagern.


  • Mod

    blue-tec schrieb:

    Hmm ja, ich hatte gehofft da gibt es was anderes außer die Members auszulagern.

    Externe Dokumentation (z.B. automatisiert mit Doxygen), private-Teil ganz nach unten schreiben, private Teil in eine includierte Datei schreiben, ...

    Sei kreativ, es gibt viele Wege.



  • blue-tec schrieb:

    Wie verstecke ich dann aber am besten meinem privaten Membervariabeln, da diese ja von der Logik her zwar auch deklariert werden müssen aber für die Schnittstellen, die der Kunde dann sehen soll, unnötiger Ballast sind?

    Private Variablen gehören per Definition nicht zur Schnittstelle. Lasse sie ruhig in der Klassendefinition stehen. Im Idealfall hast du eine separate Dokumentation in Textform (z.B. als HTML-Dateien), wo alles Private automatisch weggelassen wird. Und falls der Header die einzige Dokumentation ist, gestalte ihn eben für den Benutzer so übersichtlich wie möglich (z.B. private -Bereich möglichst weit unten).



  • ziemlich grosse diskussion ueber das thema, viele fuer const parameter, von daher werde ich sie in zukunft auch nur bei Referenzen und Zeiger benutzen,

    wie sieht eigentlich mit __in bzw __out bei parameter, ich hab das bei einige api funktionen gesehen, soll man sie eigentlich benuzten oder hat es ne "Nebenwirkung"?

    void test( __in int a, __in int b, __in int* c ) {
        *c = a + b;
    }
    

Anmelden zum Antworten