2009-03-14 6 views
143

Stavo leggendo le risposte a questa domanda C++ pros and cons e ho avuto questo dubbio mentre leggevo i commenti.Perché 'this' è un puntatore e non un riferimento?

i programmatori trovano spesso confuso che "questo" sia un puntatore ma non un riferimento. un'altra confusione è il motivo per cui "ciao" non è di tipo std :: string ma valuta un char const * (puntatore) (dopo la conversione da matrice a puntatore) - Johannes Schaub - litb 22 dic08 '1:56

Che mostra solo che non usa le stesse convenzioni di altre lingue (successive). - le dorfier 22 dicembre 08 alle 3:35

Definirei la "questa" cosa piuttosto banale. E ops, grazie per aver catturato alcuni errori nei miei esempi di comportamento indefinito. :) Sebbene non capisco quali informazioni sulla dimensione abbiano a che fare con qualcosa nel primo. Un puntatore semplicemente non è autorizzato a puntare all'esterno della memoria allocata - jalf 22 dicembre 08 alle 4:18

È un poeta costante? - yesraaj 22 dicembre 08 alle 6:35

questo può essere costante se il metodo è const int getFoo() const; < - nell'ambito di getFoo, "questo" è costante ed è quindi di sola lettura. Questo impedisce bug e fornisce un certo livello di garanzia al chiamante che l'oggetto non cambierà. - Doug T. 22 dicembre 08 alle 16:42

non è possibile riassegnare "questo". non si può fare "this = &other;", perché questo è un valore. ma questo è di tipo T *, non di tipo T const. è un puntatore non costante. se sei in un metodo const, allora è un puntatore a const. T const. ma il puntatore stesso non è coerente - Johannes Schaub - litb 22 dicembre 08 alle 17:53

pensa a "questo" come questo: #define questo (this_ + 0) dove il compilatore crea "questo_" come puntatore a l'oggetto e rende "questo" una parola chiave. non puoi assegnare "questo" perché (questo_ + 0) è un valore. naturalmente, che non è così che è (non v'è tale macro), ma può aiutare a capire che - Johannes Schaub - litb 22 dicembre '08 al 17:55

La mia domanda è, perché this è un puntatore di un non è un riferimento? Qualche ragione particolare per renderlo un puntatore?


Alcuni altri argomenti perché this di essere un punto di riferimento avrebbe senso:

  • Considerate Item 1 da More Effective C++: utilizzare i riferimenti quando è garantito che abbiamo un oggetto valido cioè non un NULL (mia interpretazione) .
  • Inoltre, i riferimenti sono considerati più sicuri dei puntatori (poiché non è possibile svuotare la memoria con un puntatore vagante).
  • In terzo luogo, la sintassi per l'accesso ai riferimenti (.) è un po 'più bella e più corta dell'accesso ai puntatori (-> o (*)).
+0

Così la gente può fare brutti hack come void foo :: something() {if (this) stuff(); }} – paulm

+3

@paulm Che cosa potrebbe veramente fare questo "hack"? Non 'questo' valuti sempre 'vero'? – iFreilicht

+0

foo * instance = nullptr; foo-> qualcosa(); // Ora se (this) == false – paulm

risposta

142

Quando il linguaggio si sviluppava per la prima volta, nelle prime versioni con utenti reali, non c'erano riferimenti, solo riferimenti. I riferimenti sono stati aggiunti quando è stato aggiunto il sovraccarico dell'operatore, in quanto richiede che i riferimenti funzionino in modo coerente.

Uno degli usi di this è che un oggetto ottenga un puntatore a se stesso.Se fosse un riferimento, dovremmo scrivere &this. D'altra parte, quando scriviamo un operatore di assegnazioni dobbiamo return *this, che sembrerebbe più semplice come return this. Quindi, se tu avessi una lista vuota, potresti discuterne in entrambi i modi. Ma C++ si è evoluto gradualmente in risposta al feedback di una comunità di utenti (come la maggior parte delle cose di successo). Il valore della retrocompatibilità travolge totalmente i piccoli vantaggi/svantaggi derivanti da this come riferimento o puntatore.

+3

Bene, spesso è anche utile per un oggetto ottenere un riferimento a se stesso. Direi che è un uso più comune. Ad ogni modo, il motivo principale è come hai detto tu, i riferimenti non esistevano quando hanno creato il puntatore "this". – jalf

+0

Se 'this' era un riferimento, l'uso principale di questo sarebbe probabilmente 'this.member' anziché 'this-> member', quindi non avresti bisogno della e commerciale la maggior parte del tempo. –

+1

sono completamente d'accordo con il tuo primo paragrafo. e penso che il suo uso principale sia ottenere l'indirizzo dell'oggetto. ma perché avrebbe bisogno di un puntatore? il riferimento andrà altrettanto bene e andrà meglio per altri casi come "this.foo" e "swap (this, bar)" –

88

Un po 'tardi alla festa ... Direttamente dalla bocca del cavallo, here's what Bjarne Stroustrup has to say (che è essenzialmente ripetuto o preso dal "Progettazione ed evoluzione di C++" libro):

Perché "questo "non un riferimento?

Perché "questo" è stato introdotto in C++ (in realtà in C con Classi) prima di aggiungere riferimenti. Inoltre, ho scelto "questo" per seguire l'uso di Simula, piuttosto che l'uso (successivo) di Smalltalk di "sé".

+0

Sì, sarebbe stato carino per coerenza con altre lingue, vabbè. – pilkch

-3

Indipendentemente da come siamo arrivati ​​qui, penso che sia una fortuna che questo è un puntatore e non un punto di riferimento come questo aiuta è "dare un senso" che si può eliminare esso:

void A::f() { 
    delete &this; 
} 

Penso che questo sia un caso in cui senza necessariamente essere di progettazione, il C++ è meglio così com'è.

+45

Direi che è una buona argomentazione per il motivo per cui dovrebbe essere un riferimento ... Le classi non dovrebbero generalmente cancellarsi. – jalf

+5

Forse non in generale - ma ci sono esempi in cui vuoi che accada. Ad esempio un puntatore intelligente intrusivo. –

+15

In questi casi potresti semplicemente scrivere 'cancella &this;' come mostrato, però :) Ci penso come con getti new-style contro conversioni implicite: fai in modo che i casi più brutti abbiano bisogno di più caratteri e facciano in modo che i casi più belli richiedano meno caratteri filosofia:) –

-2

Il C++ stati standard che

9.3.2/1

Nel corpo di una funzione membro non statica (9.3) , la parola questa è un'espressione non Ivalue cui valore è l'indirizzo dell'oggetto per cui viene chiamata la funzione . Il tipo di in una funzione membro di una classe X è X *. Se la funzione membro è dichiarato const, il tipo di questo è const X *, se la funzione membro è dichiarata volatile, il tipo di questo è volatili X *, e se la funzione membro viene dichiarata const volatile, il tipo di questo è const volatile X *.

Ma in altri riferimenti, è stato trovato qualcos'altro .. così qualcuno ha preso l'iniziativa e ha sparato una mail a Mr. Stroustrup. La conversazione che segue può essere trovata here.

+0

(A) che tratta di un aspetto diverso di "questo"; non ha rilevanza per la domanda posta. (B) Ignorando che non è rilevante, dovresti aver citato il link; SE aggrotta le sopracciglia sulle risposte solo per link.Tutta la tua risposta stessa contiene una citazione indipendente dallo standard, non una sfumatura. –