2012-01-11 9 views
11

Considere el siguiente fragmento de código:C++: implementando el método igual - ¿cómo asegurarse de que el objeto dado no sea la misma referencia que este?

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

    // check the state 
} 

El problema con este código es que SomeObject podría anular operator& (o alguien podría añadir en el futuro), que a su vez puede romper esta aplicación.

¿Es posible comprobar si rhs y *this son el mismo objeto sin estar a merced de la implementación operator&?

+0

Interesante. 'this == rhs.this' y' :: & rhs' no funcionan. ¡Buena pregunta! –

+0

@MrLister: lol at 'rhs.this' :-) ¿No debería ser' std :: that (rhs) '? –

+0

En realidad, si se trata de clases polimórficas, ¿podría ser que alguien le pasa una referencia base de '* this' y su comparación falla erróneamente? –

Respuesta

18

Si desea obtener la dirección real del objeto e ignorar sobrecargados & operadores a continuación, utilizar std::addressof

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

    // check the state 
} 

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

+3

¡Buen uso de 'addressof'! :-) –

+0

@KerrekSB por alguna razón, estaba fresco en mi mente;) – JaredPar

+0

@JaredPar: ¿Por curiosidad, cómo descubres esas funciones? Hay muchas cosas nuevas desde que salió C++ 11, pero recordarlo me parece imposible. – ereOn

-2

sólo tiene que pasar un puntero a someObject lugar de una referencia, por lo que ya no necesita el operador &.

que le gustaría esto, entonces:

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

Así que entonces tendría que hacer: SomeObject * a = ... SomeObject * b = ... if ((* a) == b) {...} ¿Es eso cierto ? Porque eso parece un poco como un truco. –

+3

-1: No, porque eso daría una semántica horrible: 'if (a == & b)' (que de hecho solo mueve el problema). –

+0

Lo siento, no lo entiendo (de hecho, me funciona). Si llama a la función con la dirección del objeto (SomeObject * rhs), entonces la función tiene el puntero con la dirección. Este también es un puntero con la dirección. Si los iguala, verá si apuntan al mismo objeto ... ¿por qué está mal? Lo siento si parezco estúpido ahora, pero luego explíquelo. – Toby

0

¿Qué pasa si se acaba de quitar esa condición en su totalidad? ¿Con qué frecuencia alguien comparará un objeto consigo mismo? Si generalmente necesita inspeccionar todos los miembros de datos de todos modos, esta simple comparación solo desperdicia tiempo en el caso promedio. Mientras no ocurra nada malo cuando los dos objetos son físicamente iguales (y su función es const, entonces debería estar bien), entonces ¿cuál es el daño al hacer un poco de trabajo adicional en este raro caso?

+0

Es fundamental cuando se escriben sobrecargas del operador de asignación cuando la clase está administrando recursos. –

+1

Sí, es crítico manejar con gracia la auto asignación *, pero el OP está escribiendo 'iguales'. –

+0

Puede ser una ganancia de rendimiento para no tener que comparar todos los miembros si ya sabes que es el mismo objeto. –

3

Hay una función std::addressof en C++ 11 que debe hacer lo que desee.

Si quisiera aplicar usted mismo, usted podría utilizar la fundición a otro tipo:

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

Sin embargo, no me molestaría; una función const equals debería funcionar bien para parámetros idénticos.

+0

Omitir el cuerpo de la prueba puede ser una optimización que vale la pena en algunos casos. –

Cuestiones relacionadas