2012-01-30 20 views
15

Estoy haciendo una revisión de mi C++, y estoy lidiando con la sobrecarga del operador en el minuto, específicamente el operador "=" (asignación). Estaba buscando en línea y encontré varios temas discutiéndolo. En mis propias notas, tengo todos mis ejemplos tomados abajo como algo parecido a¿Por qué debería el operador de asignación devolver una referencia al objeto?

class Foo 
{ 
    public: 
     int x; 
     int y; 
     void operator=(const Foo&); 
}; 
void Foo::operator=(const Foo &rhs) 
{ 
    x = rhs.x; 
    y = rhs.y; 
} 

en todas las referencias que encontré en línea, me di cuenta de que el operador devuelve una referencia al objeto de origen. ¿Por qué es la forma correcta de devolver una referencia al objeto en lugar de la nada en absoluto?

+0

La forma correcta es la forma que implementa la semántica que desee; la forma _idiomatic_ es sin duda devolver 'T &' ('Foo &' en tu ejemplo). – ildjarn

+0

@MooingDuck, creo que formulé la pregunta equivocada. Iba a suponer que mis notas estaban equivocadas, pero quería saber por qué más de lo que era correcto. – maccard

+1

posible duplicado de [operador de asignación devolver una referencia a * esto en C++] (http://stackoverflow.com/questions/5669813/assignment-operator-return-a-reference-to-this-in-c); también [Devolver * esto con un operador de asignación] (http://stackoverflow.com/questions/3248469/returnning-this-with-an-assignment-operator) –

Respuesta

17

La forma habitual devuelve una referencia al objeto de destino para permitir el encadenamiento de asignación. De lo contrario, no sería posible hacerlo:

Foo a, b, c; 
// ... 
a = b = c; 

Sin embargo, tenga en cuenta que acertar el operador assigment is tougher than it might seem.

+0

Nunca he tenido conocimiento de la parte Copiar e Intercambiar. Siempre he comprobado la autoasignación, los valores asignados y el vacío devuelto, supongo que hay más en esto de lo que esperaba. Aceptando su respuesta para señalar Copy & Swap Gracias por la respuesta. – maccard

13

tipo El retorno no importa cuando estás realizando una sola asignación en una declaración como esta:

x = y; 

Se comienza a adquirir importancia cuando se hace esto:

if ((x = y)) { 

. .. y realmente importa cuando haces esto:

x = y = z; 

Es por eso que devuelves el objeto actual: a todos encadenando asignaciones con la asociatividad correcta. Es una buena práctica general.

+0

No entiendo por qué dices "empieza a importar". O importa o no. ¿Puedes por favor elaborar? – balajeerc

+3

@balajeerc: "Empieza a importar", en inglés se dice que significa "importa en la última situación, pero no en la anterior". En otras palabras, "al cambiar de la situación A a la B, la importancia ('importar') va de cero a distinto de cero". En asignación directa, la devolución no importa. Dentro de un condicional importa si lo que devuelve es verdadero o falso, pero no exactamente qué objeto es. En el caso de asignaciones encadenadas, realmente desea que el retorno sea el objeto actual porque de lo contrario los resultados serían contrarios a la intuición. – Borealid

8

Su operador de asignación siempre debe hacer estas tres cosas:

  1. Tome una entrada const referencia (const MyClass &rhs) como el lado derecho de la asignación. La razón para esto debería ser obvia, ya que no queremos cambiar accidentalmente ese valor; solo queremos cambiar lo que está en el lado izquierdo.

  2. Siempre devuelva una referencia al lado izquierdo nuevamente alterado, return *this. Esto es para permitir el encadenamiento del operador, p. a = b = c;.

  3. Compruebe siempre la auto asignación (this == &rhs). Esto es especialmente importante cuando su clase hace su propia asignación de memoria.

    MyClass& MyClass::operator=(const MyClass &rhs) { 
        // Check for self-assignment! 
        if (this == &rhs) // Same object? 
         return *this; // Yes, so skip assignment, and just return *this. 
    
        ... // Deallocate, allocate new space, copy values, etc... 
    
        return *this; //Return self 
    } 
    
+1

La comprobación de la autoasignación es una solución ingenua, la correcta es copiar y cambiar. –

+0

Gracias por la respuesta, pero solo estaba tratando de hacer un simple ejemplo al omitir el control de auto asignación. Entendí todo lo que impide que el regreso sea una referencia. – maccard

+0

@MatteoItalia Copiar y cambiar puede ser costoso. Por ejemplo, la asignación de un vector grande a otro no puede reutilizar la memoria del objetivo si se usa copiar y cambiar. –

Cuestiones relacionadas