2014-03-13 10 views
11

Dies ist ein Zeiger auf das aufrufende Objekt (es gibt den r-Wert zurück).Was gibt & ** genau zurück?

* Dies ist ein Zeiger auf den Zeiger des aufrufenden Objekts (es gibt den Wert der Adresse zurück).

** Dies ist ein Zeiger auf den Zeiger des Zeigers des aufrufenden Objekts (???).

& *** Dies ist eine Referenz auf den Zeiger des Zeigers des Zeigers des aufrufenden Objekts (???).

std::vector<int>:: iterator i = vector1.begin(); 

i ist der Zeiger auf seinen eigenen r-Wert (gibt seinen eigenen Wert zurück).

* i ist der Zeiger eines r-Wertes eines Objekts, das in einem Vektor enthalten ist (gibt den Wert zurück, auf den in & Wert gezeigt wird).

** i ist der Zeiger auf den Zeiger eines r-Wertes eines Objekts in einem Vektor (???).

Ich bin wirklich verwirrt.

Hier ist ein Beispielcode, wo wir den Ausdruck finden & ** dieses:

class _Iter 
{ 
private: 
    ListElem *pCurr; 
    const List *pList; 

public: 
    _Iter(ListElem *pCurr, const List *list) 
     : pCurr_(pCurr), pList(list) 
    {} 

    T& operator*() { return pCurr_->data; } 
    T* operator->() { return &**this; } 
}; 
+0

Der Aufrufer erhält '& pCurr-> data'. –

+1

Sie müssen sich daran erinnern, dass '*' genau rückwärts arbeitet, je nachdem, ob es sich um eine Deklaration oder eine ausführbare Anweisung handelt. –

+0

"Dies ist ein Zeiger auf das aufrufende Objekt (es gibt den r-Wert zurück)" benannte Variablen können nicht r-Wert sein –

Antwort

20

this ist ein Zeiger auf das aktuelle Objekt.

*this ist eine Referenz auf das aktuelle Objekt, d.h. this dereferenziert.

**this ist der zurückgegebene Wert der überladenen unären operator*-Funktion, die für das aktuelle Objekt aufgerufen wird.

Wenn das von **this zurückgegebene Objekt eine überladene operator&()-Funktion aufweist, wird &**this zum zurückgegebenen Wert von (**this).operator&() ausgewertet. Andernfalls ist &**this der Zeiger auf den zurückgegebenen Wert der überladenen unären operator*-Funktion, die für das aktuelle Objekt aufgerufen wird.

Beispiel:

#include <iostream> 

struct A 
{ 
    int b; 
    int a; 
    int& operator*() {return a;} 

    int* test() 
    { 
     return &**this; 
    } 
}; 

int main() 
{ 
    A a; 
    std::cout << "Address of a.a: " << a.test() << std::endl; 
    std::cout << "Address of a.a: " << &(*a) << std::endl; 
    std::cout << "Address of a.a: " << &(a.a) << std::endl; 
    return 0; 
} 

Beispielausgabe:

Address of a.a: 0x7fffbc200754 
Address of a.a: 0x7fffbc200754 
Address of a.a: 0x7fffbc200754 
+7

Sehen Sie, ob dies es klarer (oder verwirrender) macht: '** this' kann als 'this -> operator *()' interpretiert werden. Deshalb ist '& ** this' '' & (this-> operator *()) 'was die Adresse des zurückgegebenen Wertes des überladenen' * 'Operators für das aktuelle Objekt nimmt: P –

+1

' & ** this 'könnte' 'sein operator & hat den Rückgabewert des unären Operators * 'aufgerufen. In der Tat, wenn der 'Operator *' eine Nicht-Referenz zurückgibt, dann muss es sein, wie Sie die Adresse eines temporären nicht nehmen können. –

+0

@MattMcNabb, ausgezeichnete Punkte. –

2

Wenn Sie eine Klasse Foo und ein Verfahren dieser Klasse, die this und das Objekt verwenden Foo obj dann

this - ist ein Wert vom Typ pointer to Foo, der einen Wert der Adresse des Objektshat

so können Sie so schreiben (zum Beispiel in Foo: Test()):

Foo *addr = this; 

so addr ist eine Variable vom Typ pointer to Foo, die mit einem Adresswert des Objekts obj der Klasse initialisiert wird Foo .

Alle Zeiger in C++ können mit * dereferenziert werden. Also, wenn Sie dereferenzieren einen Zeiger auf ein Objekt erhalten Sie das Objekt

Foo *addr = get_pointer_to(obj); //function that return a pointer to object 

//three equivalent ways to call someMethod() of object obj of class Foo 
obj.someMethod(); 
addr->someMethod(); 
(*addr).someMethod(); 

Oberteil des Codes zeigt, dass Objekt obj und dereferenzierten Zeiger (*addr) die gleiche Syntax haben, weil sie das gleiche Objekt sind.

In C++ können Sie verschiedene Sprachenoperatoren überladen. Wenn Sie also schreiben (** das), sieht der Compiler nach this und stellt fest, dass this die Art des Zeigers auf Foo ist, so dass der Dereferenzierung *this Objekt des Typs Foo gibt. Dann findet der Compiler (* (*this)). Aber Foo ist kein Typ des Zeigers, daher gibt es standardmäßig keinen Operator *. Der Compiler wird also einen Fehler zurückholen und die Kompilierung unterbrechen. Aber wenn Sie operator*() in Klasse Foo (überladen) definieren, ruft der Compiler diese Methode auf. So entspricht **thisthis->operator*() oder (*this).operator*().

Der letzte ist operator&(). Standardmäßig gibt dieser Operator einen Zeiger auf das Objekt zurück. Aber natürlich kann es überlastet sein und etwas anderes zurückgeben. &**this kann, so das Rück 1) eine Adresse des Objekts, das durch operator*() angewandt auf das Objekt (* this)
2) Rückgabewert Methode operator&() des Objekts, die zurückgegeben wurde durch operator*() die angewandt wurde, um (* this zurückgegeben wurde) . Wenn keine operator*() definiert ist, wird &**this nicht kompiliert.

Zusätzlich gibt es keine operator*() definiert und keine operator&() definiert dann die Konstruktion von &**some_pointer wird entweder nicht kompilieren oder wird (* some_pointer) zurückgeben. Und ich kann garantieren, dass (* some_pointer) ein Zeiger ist.