15

Sto eseguendo alcune revisioni del mio C++ e ho a che fare con il sovraccarico dell'operatore al minuto, in particolare con l'operatore "=" (assegnazione). Stavo cercando online e ho incontrato più argomenti per discuterne. Nei miei appunti, ho tutti i miei esempi presi in giù come qualcosa di simile aPerché l'operatore di assegnazione dovrebbe restituire un riferimento all'oggetto?

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

In tutti i riferimenti che ho trovato on-line, ho notato che l'operatore restituisce un riferimento all'oggetto di origine. Perché è il modo corretto per restituire un riferimento all'oggetto in contrasto con il nulla?

+0

Il modo corretto è qualunque modo implementa la semantica che si desidera; il modo _idiomatic_ è certamente quello di restituire 'T &' ('Foo &' nel tuo esempio). – ildjarn

+0

@MooingDuck, immagino di aver sbagliato la domanda. Stavo partendo dal presupposto che i miei appunti erano sbagliati, ma volevo sapere perché più di quello era corretto. – maccard

+1

possibile duplicato di [operatore di assegnazione restituisce un riferimento a * questo in C++] (http://stackoverflow.com/questions/5669813/assignment-operator-return-a-reference-to-this-in-c); anche [Restituzione * di questo con un operatore di assegnazione] (http://stackoverflow.com/questions/3248469/returning-this-with-an-assignment-operator) –

risposta

17

Il solito modulo restituisce un riferimento all'oggetto di destinazione per consentire il concatenamento di assegnazione. In caso contrario, non sarebbe possibile fare:

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

Eppure, tenere a mente che ottenere proprio l'operatore assigment is tougher than it might seem.

+0

Mai saputo della parte Copy and Swap. Ho sempre controllato l'auto assegnazione, i valori assegnati e restituito nulla, immagino ci sia molto di più di quanto mi aspettassi. Accettare la tua risposta per indicare la copia e lo scambio Grazie per la risposta. – maccard

13

tipo Il ritorno non importa se si sta solo eseguendo un singolo incarico in una dichiarazione come questa:

x = y; 

Si inizia alla materia, quando si esegue questa operazione:

if ((x = y)) { 

. .. e conta davvero quando si esegue questa operazione:

x = y = z; 

Ecco perché si restituisce l'oggetto corrente: a tutti ow chaining assegnazioni con l'associatività corretta. È una buona pratica generale.

+0

Non capisco perché dici "comincia a importare". O importa o no. Puoi per favore elaborare? – balajeerc

+3

@balajeerc: "Comincia a dire" in inglese si legge per significare "conta nella seconda situazione ma non nella prima". In altre parole, "quando si passa dalla situazione A alla B, l'importanza (" che importa ") passa da zero a non zero". Nell'assegnazione diretta il ritorno non ha importanza. All'interno di un condizionale importa se la cosa che si restituisce è vera o falsa, ma non esattamente quale oggetto è. Nel caso degli assegnamenti concatenati, si desidera veramente che il ritorno sia l'oggetto corrente perché altrimenti i risultati sarebbero controintuitivi. – Borealid

8

vostro operatore di assegnazione dovrebbe sempre fare queste tre cose:

  1. Prendere un ingresso const riferimento (const MyClass &rhs) come il lato destro della cessione. La ragione di ciò dovrebbe essere ovvia, dal momento che non vogliamo modificare accidentalmente quel valore; vogliamo solo cambiare ciò che è sul lato sinistro.

  2. Restituire sempre un riferimento al lato sinistro appena modificato, return *this. Questo per consentire il concatenamento dell'operatore, ad es. a = b = c;.

  3. Controllare sempre l'assegnazione automatica (this == &rhs). Questo è particolarmente importante quando la tua classe fa la propria allocazione di 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

Controllare l'autoassegnazione è una soluzione ingenua, quella corretta è copy-and-swap. –

+0

Grazie per la risposta, ma stavo solo cercando di fare un semplice esempio tralasciando il controllo dell'auto assegnazione. Ho capito tutto ciò che rende il ritorno un riferimento. – maccard

+0

@MatteoItalia Copy-and-swap può essere costoso. Ad esempio, l'assegnazione di un vettore di grandi dimensioni a un altro non può riutilizzare la memoria del bersaglio se viene utilizzata la copia e lo swap. –

Problemi correlati