2012-01-11 12 views
11

Si consideri il seguente frammento di codice:C++: implementazione del metodo uguale: come assicurarsi che l'oggetto indicato non sia lo stesso di riferimento?

bool SomeObject::equal(const SomeObject& rhs) const 
{ 
    if (this == &rhs) 
    { 
    return true; 
    } 

    // check the state 
} 

Il problema con questo codice è che SomeObject potrebbe ignorare operator& (o qualcuno potrebbe aggiungere in futuro), che a sua volta può rompere questa implementazione.

È possibile verificare se rhs e *this sono lo stesso oggetto senza essere in balia dell'implementazione di operator&?

+0

Interessante. 'this == rhs.this' e' :: & rhs' non funzionano. Buona domanda! –

+0

@MrLister: lol a 'rhs.this' :-) Non dovrebbe essere' std :: that (rhs) '? –

+0

In realtà, se hai a che fare con classi polimorfiche, potrebbe essere che qualcuno ti passi un riferimento di base di * * questo? E il tuo paragone fallisce erroneamente? –

risposta

18

Se si desidera ottenere l'indirizzo reale dell'oggetto e ignorare sovraccaricati & operatori quindi utilizzare std::addressof

bool SomeObject::equal(const SomeObject& rhs) const 
{ 
    if (this == std::addressof(rhs)) 
    { 
    return true; 
    } 

    // check the state 
} 

Riferimento: http://en.cppreference.com/w/cpp/memory/addressof

+3

Bel uso di 'addressof'! :-) –

+0

@KerrekSB per qualche motivo era fresco nella mia mente;) – JaredPar

+0

@JaredPar: Per curiosità, come fai a scoprire tali funzioni? C'è un sacco di roba nuova da quando C++ 11 è uscito, ma ricordare tutto mi sembra impossibile. – ereOn

-2

Basta passare un puntatore a someObject invece di un riferimento, in modo da non serve più l'operatore &.

vorrebbe questo allora:

bool SomeObject::equal(const SomeObject* rhs) const 
{ 
    if (this == rhs) 
    { 
     return true; 
    } 
    //... 
} 
+0

Allora dovreste fare: SomeObject * a = ... SomeObject * b = ... if ((* a) == b) {...} È quello giusto ? Perché sembra un po 'un hack. –

+3

-1: No, perché darebbe una semantica orribile: "if (a == & b)" (che di fatto sposta semplicemente il problema). –

+0

Scusa se non capisco (in realtà funziona per me). Se chiama la funzione con l'indirizzo dell'oggetto (SomeObject * rhs), allora la funzione stessa ha il puntatore con l'indirizzo. Questo è anche un puntatore con l'indirizzo. Se li uguaglia vedi se indicano lo stesso oggetto ... perché è sbagliato? Scusate se sembro stupido ora, ma per favore spiegatelo. – Toby

0

Che cosa succede se appena rimosso questa condizione del tutto? Quante volte qualcuno sta andando a confrontare un oggetto con se stesso? Se in genere è necessario ispezionare tutti i membri dei dati, allora questo semplice paragone semplicemente perde tempo nel caso medio. Finché non succede nulla di male quando i due oggetti sono fisicamente uguali (e la tua funzione è const, quindi dovresti stare bene), allora cosa c'è di male nel fare un piccolo lavoro extra nel caso raro?

+0

È fondamentale quando si scrivono sovraccarichi dell'operatore di assegnazione quando la classe sta gestendo le risorse. –

+1

Sì, è fondamentale gestire con garbo * l'auto * *, ma l'OP sta scrivendo 'equals'. –

+0

Potrebbe essere un guadagno in termini di prestazioni per non dover confrontare tutti i membri se sai già che si tratta dello stesso oggetto. –

3

C'è una funzione std::addressof in C++ 11 che dovrebbe fare quello che vuoi.

Se si voleva implementare da soli, è possibile utilizzare fusione ad un altro tipo:

(SomeClass*)&reinterpret_cast<char&>(rhs) 

Tuttavia, non vorrei perdere tempo; una funzione const equals dovrebbe funzionare correttamente per parametri identici.

+0

Saltare il corpo del test può essere un'ottimizzazione utile in alcuni casi. –

Problemi correlati