const bei Variablen als Funktionsparameter



  • TyRoXx schrieb:

    tommy_tom_tom schrieb:

    void multi(int var__) 
    {
        return var__*var__;
    }
    

    Bezeichner mit doppelten Unterstrichen sind reserviert. Das ist also undefiniertes Verhalten (wenn der Rückgabetyp stimmen würde).

    ⚠ Wusst ich nicht... wer sagt einem denn so-was, also erst jetzt?


  • Mod

    tommy_tom_tom schrieb:

    Ist mit gcc ohne jegliche Optimierung kompiliert.



  • camper schrieb:

    tommy_tom_tom schrieb:

    Ist mit gcc ohne jegliche Optimierung kompiliert.

    kein -O ... oder weitere manuell zu aktivierenden Optionen.



  • tommy_tom_tom schrieb:

    camper schrieb:

    tommy_tom_tom schrieb:

    Ist mit gcc ohne jegliche Optimierung kompiliert.

    kein -O ... oder weitere manuell zu aktivierenden Optionen.

    Oder willst auf g++ hinaus? 😕



  • camper schrieb:

    Klammerung spielt bei decltype nur eine Rolle, wenn es der Ausdruck ohne Klammer ein id-Ausdruck oder ein Klassenmemberzugriff ist (hier nicht der Fall).

    Ok, dann hatte ich das falsch in Erinnerung. Ich dachte, man kommt noch an den deklarierten Rückgabetypen einer Funktion dran.



  • tommy_tom_tom schrieb:

    camper schrieb:

    tommy_tom_tom schrieb:

    Ist mit gcc ohne jegliche Optimierung kompiliert.

    kein -O ... oder weitere manuell zu aktivierenden Optionen.

    camper wollte sagen, Performance-Vergleiche ohne Optimierung, also kein Release-Build, machen keinen Sinn. Du gibst deinem Kunden ja auch keine Debug-Version oder ;).



  • out schrieb:

    tommy_tom_tom schrieb:

    camper schrieb:

    tommy_tom_tom schrieb:

    Ist mit gcc ohne jegliche Optimierung kompiliert.

    kein -O ... oder weitere manuell zu aktivierenden Optionen.

    camper wollte sagen, Performance-Vergleiche ohne Optimierung, also kein Release-Build, machen keinen Sinn. Du gibst deinem Kunden ja auch keine Debug-Version oder ;).

    Klar, geb ich -> Bananen sind im Trend. 🕶



  • out schrieb:

    tommy_tom_tom schrieb:

    camper schrieb:

    tommy_tom_tom schrieb:

    Ist mit gcc ohne jegliche Optimierung kompiliert.

    kein -O ... oder weitere manuell zu aktivierenden Optionen.

    camper wollte sagen, Performance-Vergleiche ohne Optimierung, also kein Release-Build, machen keinen Sinn. Du gibst deinem Kunden ja auch keine Debug-Version oder ;).

    Ok, um der berechtigten, leisen Kritik von camper nachzukommen.
    Mit -O2 ist's rille wie man's formuliert.
    Zumindest kann ich keinen Unterschied feststellen (ich hatte auch grössere Werte eingesetzt - hab den Test nur für die Generics reduziert - welche in dem Fall langsamer sind)

    Man müsste wohl das Szenario anders gestalten oder es ist eben Rille 😉 ...

    #include <vector>
    
    typedef int TYPE_test;
    static constexpr TYPE_test test_size{50000};
    static std::vector<int> test_vector{};
    
    void loop(int  condition__)
    {
        for(TYPE_test  i{0} ; i!=condition__ ; ++i)
            test_vector[i] = 0;
    }
    
    void loop_const(TYPE_test  const condition__)
    {
        for(TYPE_test  i{0} ; i!=condition__ ; ++i)
            test_vector[i] = 0;
    }
    
    void loop_const_copy(TYPE_test condition__)
    {
        TYPE_test const condition_copy{condition__};
        for(TYPE_test  i{0} ; i!=condition_copy ; ++i)
            test_vector[i] = 0;
    }
    
    void loop_const_ref(TYPE_test condition__)
    {
        TYPE_test const& condition_ref{condition__};
        for(TYPE_test  i{0} ; i!=condition_ref ; ++i)
            test_vector[i] = 0;
    }
    
    void loop_const_byref(TYPE_test const& condition_ref__)
    {
        for(TYPE_test  i{0} ; i!=condition_ref__ ; ++i)
            test_vector[i] = 0;
    
    }
    
    // Generic 1
    template <TYPE_test i>
    struct Int2Type{ enum{value = i};};
    void gen_loop(Int2Type<0>)
    {}
    
    template<TYPE_test i>
    void gen_loop(Int2Type<i>)
    {
        test_vector[i] = 0;
        gen_loop(Int2Type<i-1>());
    }
    
    // Generic 2
    template<TYPE_test i>struct genLOOP{
    static inline void EXEC()
    {
        test_vector[i] = 0;
        genLOOP<i-1>::EXEC();
    }};
    
    template<>struct genLOOP<0>{static inline void EXEC(){/* loop end */}};
    
    int main()
    {
        test_vector.resize(test_size);
        for(TYPE_test i{0}; i!=test_size ; ++i)
            //loop(test_size);                      // : 0.85
            //loop_const(test_size);                // : 0.85
            //loop_const_copy(test_size);           // : 0.85
            //loop_const_ref(test_size);            // : 0.85
            //loop_const_byref(test_size);          // : 0.85
            //gen_loop(Int2Type<test_size>());      // 1.77
            //genLOOP<test_size>::EXEC();           // 1.87
    
        return 0;
    }
    

    Wer Zeit hat kann gern die Werte erhöhen und das ne halbe Stunde laufen lassen... 👍



  • Sone schrieb:

    Dieselbe Frage habe ich auch mal gestellt, und bekam als Antwort, dass man so wenig wie möglich über die Implementierung der Funktion nach außen geben sollte - sei es durch die Typen von Funktionsargumenten o. ä.
    Also, Parameter const machen schön lassen. Es bringt keinen Vorteil, gerade nicht bei solch einem Einzeiler.

    Parameter top-level const machen gibt keinerlei Auskunft über die Implementierung, da top-level const bei Parametern nicht Teil der Signatur ist.

    Konkret anhand eines Beispiels... Folgendes ist OK:

    void Foo(int x);
    
    void Foo(int const x) // implementiert void Foo(int), weil void Foo(int) das selbe ist wie void Foo(int const)
    {
    }
    

    Heisst: top-level const von Parametern bei Prototypen immer weglassen, weil es nichtssagend ist, und bloss verwirrt.

    Bei der Implementierung kann man es hinschreiben, wenn man unbedingt mag, aber ich persönlich tu' es auch nicht. (Was aber bloss Gewohnheitssache ist, und nicht weil ich es für schlecht halte.)



  • Das Weglassen vom top-level-const bezieht sich aber jetzt nur auf Nicht-Zeiger/Nicht-Referenz-Typen, oder? Würde ja auch keinen Sinn ergeben - nur um ganz sicherzugehen.



  • Eisflamme schrieb:

    Das Weglassen vom top-level-const bezieht sich aber jetzt nur auf Nicht-Zeiger/Nicht-Referenz-Typen, oder? Würde ja auch keinen Sinn ergeben - nur um ganz sicherzugehen.

    Nur um ganz sicherzugehen, welches const meinst Du?

    //     A     B             C      D              E
    int const* const foo(int const* const cpci,int const& ri);
    


  • Eisflamme schrieb:

    Das Weglassen vom top-level-const bezieht sich aber jetzt nur auf Nicht-Zeiger/Nicht-Referenz-Typen, oder? Würde ja auch keinen Sinn ergeben - nur um ganz sicherzugehen.

    "Top-Level" bezieht sich ja gerade auf das äusserste const .

    Referenzen qualifiziert man ohnehin nicht const , und für konstante Zeiger gilt das gleiche wie für andere Parameter (nämlich das, was hustbaer gesagt hat).



  • ISO/IEC 14882:2011 8.3.5 Functions 5

    ... The type of a function is determined using the following rules. The type of each parameter (including function parameter packs) is determined from its own decl-specifier-seq and declarator. After determining the type of each parameter, any parameter of type “array of T” or “function returning T” is adjusted to be “pointer to T” or “pointer to function returning T,” respectively. After producing the list of parameter types, any top-level cv-qualifiers modifying a parameter type are deleted when forming the function type. ...



  • Ich meine C und E, das wäre ja sinnlos, wenn die wegfallen/ignoriert werden.

    Aber den Standardauszug von dd+ hilft mir leider nicht, weil ich decl-specifier-seq, declarator und cv-qualifier nicht verstehe. Wo würde man C-E denn in diese Begriffe einordnen?

    Edit: Ah, nach Nexus' post habe ich erst kapiert, dass ich top-level missverstanden hatte. Trotz der mir fehlenden Begriffsdefinitionen des Standardauszugs verstehe ich diesen nun, danke. 🙂



  • E ist kein top-level Qualifier, denn der Typ ist "Referenz auf const int" und der top-level Typ ist "Referenz", E gehört aber zum untergeordneten Typ "const int"

    cv-qualifier ist const oder volatile



  • Ja, stimmt natürlich, top-level ist das nicht. Nach Verständnis des Wortes "top-level" verstand ich das auch. Gemeint war meine Frage nur darauf bezogen, ob C und E auch ihr const verlieren, was natürlich keinen Sinn ergibt und mir jetzt auch nach Definition klar ist. 🙂 Also C ist demnach ja auch kein top-level, D aber eben schon.

    Danke auch für cv-Qualifier-Erklärung! Ich könnte jetzt noch nachfragen, ob es denn überhaupt noch andere Qualifier gibt, aber ich will den Thread ja nicht sprengen. Außerdem müsste man mir dann vorwerfen, dass ich nicht so faul sein soll und gefälligst selbst Mal im Standard die Definitionen nachlesen könnte.



  • ...



  • kurze Zusammenfassung: in folgendem Code sind die Deklarationen für f und g gleich, für h werden aber 2 versch. Funktionen deklariert

    void f (      int i);
    void f (const int i);
    void g (int *       pi);
    void g (int * const pi);
    void h (      int * pci);
    void h (const int * pci);
    


  • tommy_tom_tom schrieb:

    Mit -O2 ist's rille wie man's formuliert.

    Ja, ist auch nicht verwunderlich. const existiert im kompilierten Code nicht mehr.



  • dd++ schrieb:

    kurze Zusammenfassung: in folgendem Code sind die Deklarationen für f und g gleich, für h werden aber 2 versch. Funktionen deklariert

    void f (      int i);
    void f (const int i);
    void g (int *       pi);
    void g (int * const pi);
    void h (      int * pci);
    void h (const int * pci);
    

    Nur zur Ergänzung: das ganze wird logischer wenn man es so schreibt:

    void f (int       i);
    void f (int const i);
    void g (int *       pi);
    void g (int * const pi);
    void h (int       * pci);
    void h (int const * pci);
    

    [/quote]
    Dann ist nämlich immer wenn const das rechteste Element in der deklaration ist, das const nicht teil der funktionssignatur.

    Ich persönlich schreibe deshalb lieber das const auf die rechte Seite - es liest sich dann auch logischer (von rechts nach links).


Anmelden zum Antworten