Rechstassoziativität unärer Operatoren



  • Hallo,

    habe gerade gelesen, dass aufgrund der Rechtsassoziativität von Operatoren folgender Ausdruck auf folgende Weise umgesetzt wird:

    *ziel++ = *quelle++;
    
    // entspricht:
    
    ziel.operator++().operator*(int).operator=(*quelle++);
    // entspricht, mit erg1 = Ergebnis/Rückgabewert von ziel.operator++()
    erg1.operator*(int).operator=(*quelle++);
    // entspricht, mit erg2 = Ergebnis/Rückgabewert von erg1.operator*(int)
    erg2.operator=(*quelle++);
    

    Wenn ich von dem ganz einfachen Fall der Zuweisung der Werte zwischen zwei arrays mittels Zeigerarithmetik ausgehe:

    int a[5];
    for(int i = 0; i < 5; ++i)
        a[i] = i;
    int b[5];
    int* aptr = a;
    int* bptr = b;
    for(int i = 0; i < 5; ++i)
    {
        *bptr++ = *aptr++;
    }
    

    ...dann erfolgt doch erst die Derefernzierung und dann die Inkrementierung, d.h.

    *bptr++ = *aptr++;
    // entspricht
    *bptr = *aptr;
    bptr++;
    aptr++;
    

    Oder schmeiße ich da jetzt etwas durcheinander? Kann mich jemand aufklären?

    Danke!



  • jklö schrieb:

    *ziel++ = *quelle++;
    
    // entspricht:
    
    ziel.operator++().operator*(int).operator=(*quelle++);
    

    Das ist schon falsch. Korrekt wäre:

    ziel.operator ++(int()).operator *().operator =(*quelle+);
    

    D.h. der 'int'-Parameter gehört zum Postfix-Inkrement, nicht zur Dereferenzierung.

    ...dann erfolgt doch erst die Derefernzierung und dann die Inkrementierung

    Genau.



  • Konrad Rudolph schrieb:

    der 'int'-Parameter gehört zum Postfix-Inkrement, nicht zur Dereferenzierung.

    Ooops, das habe ich zweimal in das falsche Klammernpaar gepackt, sorry.
    Aber das ist mir schon klar: Präfix- und Postfix-Inkrement unterscheiden sich durch die Übergabe des int.

    Also, ich korrigiere das noch einmal, weil es an meiner eigentlichen Frage nichts ändert:

    *ziel++ = *quelle++;
    
    // entspricht:
    
    ziel.operator++(int).operator*().operator=(*quelle++);
    // entspricht, mit erg1 = Ergebnis/Rückgabewert von ziel.operator++()
    erg1.operator*().operator=(*quelle++);
    // entspricht, mit erg2 = Ergebnis/Rückgabewert von erg1.operator*(int)
    erg2.operator=(*quelle++);
    

    Trotzdem ist es doch dann offensichtlich so, dass der Inkrement-operator (in diesem Fall) zuerst ausgewertet wird: der Rückgabewert des Inkrement-Operators wird dereferenziert, oder nicht?
    Also genau andersherum als im Fall der Zeigerarithmetik.

    Sorry, aber ich verstehe es immer noch nicht 😕



  • Jetzt verstehe ich Deine Frage erst. ^^

    jklö schrieb:

    Trotzdem ist es doch dann offensichtlich so, dass der Inkrement-operator (in diesem Fall) zuerst ausgewertet wird: der Rückgabewert des Inkrement-Operators wird dereferenziert, oder nicht?
    Also genau andersherum als im Fall der Zeigerarithmetik.

    Nein. Du musst Dir deutlich machen, was innerhalb des Operators ++(int) passiert:

    struct T {
        T operator ++(int)
        {
            T ret = *this; // hier wird eine Kopie von *this erstellt!
            ++*this;       // *this inkrementieren
            return ret;    // unveränderte (!) Kopie zurückgeben.
        }
    }
    

    Im Prinzip hast Du also recht: Es wird der Rückgabewert des Inkrement-Operators dereferenziert. Aber bei diesem Wert handelt es sich um eine Kopie des eigentlichen Zeigers, bevor er dereferenziert wurde.

    Spiel das ganze mal mit Indizes als Zeigerwerten nach, dann solltest Du es verstehen (also, am Anfang sind beide auf null, dann wird innerhalb von 'op++(int)' der Wert kopiert (ret = 0), erhöht (quelle = 1) und der Rückgabewert dereferenziert, also *0).



  • Konrad Rudolph schrieb:

    Im Prinzip hast Du also recht: Es wird der Rückgabewert des Inkrement-Operators dereferenziert. Aber bei diesem Wert handelt es sich um eine Kopie des eigentlichen Zeigers, bevor er dereferenziert wurde.

    ...was ja gerade den Unterschied zwischen Postfix und Präfix ausmacht...Oje, da bin ich jetzt aber schwer auf der Leitung gestanden!!!

    Danke jedenfalls für die Erläuterungen, ich sehe wieder klar.



  • Aber bei diesem Wert handelt es sich um eine Kopie des eigentlichen Zeigers, bevor er dereferenziert wurde.

    Nö, bevor er inkrementiert wurde 😉



  • hustbaer schrieb:

    Aber bei diesem Wert handelt es sich um eine Kopie des eigentlichen Zeigers, bevor er dereferenziert wurde.

    Nö, bevor er inkrementiert wurde 😉

    Äh, ja, das meinte ich. 😉


Anmelden zum Antworten