this Zeiger



  • drakon schrieb:

    9.3.2 The this pointer [class.this]
    1 In the body of a nonstatic (9.3) member function, the keyword this is a non-lvalue expression whose
    value is the address of the object for which the function is called. The type of this in a member function
    of a class X is X*. If the member function is declared const, the type of this is const X*, if the member
    function is declared volatile, the type of this is volatile X*, and if the member function is
    declared const volatile, the type of this is const volatile X*.

    this ist also ein ganz normaler Zeiger vom Typ const T*. (je nachdem noch der der volatile Bezeichner.)

    Somit verhält sich this, wie jeder andere const Zeiger ebenfalls.

    In deiner zitierten Textstelle steht aber was ganz anderes? 😕
    Außerdem beschreibt "const T*" den Typ eines (veränderlichen) Zeigers auf ein konstantes T und nicht den Typ eines konstanter Zeigers auf ein (veränderliches) T.



  • Hmm. Ich hab da jetzt übereilig da was hingeschrieben. Wenn überhaupt müsste ja der Zeiger const sein. (Das andere ist natürlich klar, wenn das Objekt const ist, dann ist, dann zeigt auch der Zeiger auf ein Konstates Objekt). Aber ich hatte wirklich im Kopf, dass this vom Typ T *const ist.. Das verwirrt mich jetzt doch ein bisschen. Macht ja keinen Sinn this etwas zuweisen zu wollen..



  • drakon schrieb:

    9.3.2 The this pointer [class.this]
    1 In the body of a nonstatic (9.3) member function, the keyword this is a non-lvalue expression whose
    value is the address of the object for which the function is called. The type of this in a member function
    of a class X is X*. If the member function is declared const, the type of this is const X*, if the member
    function is declared volatile, the type of this is volatile X*, and if the member function is
    declared const volatile, the type of this is const volatile X*.

    this ist also ein ganz normaler Zeiger vom Typ const T*. (je nachdem noch der der volatile Bezeichner.)

    Somit verhält sich this, wie jeder andere const Zeiger ebenfalls.

    Also den Text aus dem aktuellen Draft des Standards kann ich nur bestätigen, hab' da mal reingesehen, und Drakon's Post ist mit diesem Inhaltsgleich.

    Mein Visual Studio zeigt mir für 'this' auch bei folgender Klasse die in dem Text beschriebenen Datentypen an, somit wurde es dort auch so implementiert:

    class CThis
    {
    public:
         int i;
    
         void CV-Unqualified(void)
         {
              int a = this->i;     // CThis *const this
              // Konstanter Zeiger (rvalue) auf CThis
         };
    
         void C-Qualified(void) const
         {
              int a = this->i;     // const CThis *const this
              // Konstanter Zeiger (rvalue) auf konstantes CThis
         };
    
         void V-Qualified(void) volatile
         {
              int a = this->i;     // volatile CThis *const this
              // Konstanter Zeiger (rvalue) auf volatile CThis
         };
    
         void CV-Qualified(void) const volatile
         {
              int a = this->i;     // volatile const CThis *const this
              // Konstanter Zeiger (rvalue) auf konstantes volatile CThis
         };
         CThis(){};
         ~CThis(){};
    
    };
    

    In jedem der Fälle handelt es sich, wie wieder im Std gut beschrieben, um einen non-lvlaue (also ein rvalue), dem ja sowieso nichts zuweisbar ist. Somit, finde ich, passt die Fehlermeldung die DWeb bekommt allemal.

    Gruß
    PuerNoctis 🙂



  • Ja, passen tuts allemal. Mich wundert einfach nur, dass der Zeiger per Standard nicht const sein muss. (non-lvalue verhindert natürlich Zuweisung, aber ich finds trotzdem ein wenig komisch..)



  • Hm, vielleicht hat Microsoft das so implementiert, dass ein non-lvalue im VC nur durch ein const-Verhalten überhaupt existieren kann. Somit würde sich das T*const wohl eher durch den Compiler ergeben, und muss nicht durch den Standard definiert sein. Hab' das jetzt leider nicht mit dem GCC geprüft oder anderen Compilern, ob das bei denen auch T*const ist.

    Könnte mir aber wirklich gut vorstellen, dass dem Std egal ist WIE der rvalue entsteht, Hauptsache er ist einer^^. Wäre für mich zumindet eine logische Erklärung...

    Gruß
    PuerNoctis



  • Oh mein Gott, folgendes funktioniert:

    #include <iostream>
    
    class CThis
    {
    public:
         int i;
    
         void Umbiegen(void)
         {
              CThis Other;
              Other.i = 666;
              (const_cast<CThis*>(this)) = &Other;
              std::cout << this->i;
         };
    
         CThis() : i(0){};
         ~CThis(){};
    
    };
    
    int main(int argc, char** argv)
    {
         CThis Test;
         Test.Umbiegen();
         return 0;
    }
    

    Ausgabe:
    666



  • PuerNoctis schrieb:

    Hm, vielleicht hat Microsoft das so implementiert, dass ein non-lvalue im VC nur durch ein const-Verhalten überhaupt existieren kann.

    Dann würde

    struct foo
    {
        void bar() {}
    };
    int main()
    {
        foo().bar();
    }
    

    Ja gar nicht gehen (weil bar non-const und non-lvalue). Oder hab ich dich falsch verstanden?

    Bei GCC ist this übrigens kein rvalue, was sich einfach dadurch beweisen lässt, dass folgendes kompiliert:

    template<typename T>
    void test(T&){}
    
    struct foo
    {
        void bar()
        {
            test(this);
        }
    };
    

    Mit richtigen rvalues kompiliert das nicht. (z.B. test(foo()))



  • Du rufst da einfach eine Funktion auf ein tempotäres Objekt auf.



  • Ryuzaki schrieb:

    Bei GCC ist this übrigens kein rvalue, was sich einfach dadurch beweisen lässt, dass folgendes kompiliert:

    template<typename T>
    void test(T&){}
    
    struct foo
    {
        void bar()
        {
            test(this);
        }
    };
    

    Mit richtigen rvalues kompiliert das nicht. (z.B. test(foo()))

    Ich fürchte (drakon bestätigend), in T steckt am ende genug const, daß ein temoptäres Objekt gebaut wird.

    #include <iostream>
    using namespace std;
    
    struct foo
    {
    	static void test(foo*const& th)
    	{
    	}
    	void bar()
    	{
    			test(this+1);
    	}
    };
    
    int main() {
    	foo f;
    	f.bar();
    }
    

  • Mod

    Skalare rvalues sind niemals cv-qualifiziert und zwar einfach deshalb, weil es handelt sich nicht um Objekte handelt, d.h. Speicherbereiche, deren Inhalt man sich als änderbar vorstellen könnte. (3.10/9)


Anmelden zum Antworten