2011-08-21 12 views
7

Qualche tempo fa mi è stato detto che il solito schema per implementare gli operatori two-ary ha bisogno di un finale move nel ritorno.L'operatore C++ 0x T + (const T &, T &&), ha ancora bisogno di muoversi?

Matrix operator+(const Matrix &a, Matrix &&b) { 
    b += a; 
    return std::move(b); 
} 

Ma ora v'è la regola speciale che in un return il compilatore può trattare il valore di ritorno come temporanea, e poi questo non sarebbe necessario - un semplice return b sarebbe sufficiente.

Ma poi di nuovo, b ha un nome in questa funzione, quindi, il suo un Ivalue - che impedisce al compilatore di m ritiene che sia una temperatura, ed è richiesta l'move.

E 'ancora il caso nella versione più recente dello standard C++ 0x? Abbiamo bisogno dello move per implementare il modello sopra?

+2

Secondo [questa risposta] (http://stackoverflow.com/questions/6009004/are-value-parameters-implicitly-moved-when -returned-by-value/6009012 # 6009012), 'std :: move' non è necessario. – fredoverflow

+2

Anche se potrebbe fare la differenza che il parametro sia un 'Matrix &&' invece di un 'Matrix' ... – fredoverflow

+2

È * complicato, sì. E sì, penso che tu abbia ragione. Se è un parametro * di valore * come 'Matrix', allora hai una copia vergine per te da solo - una temp. Il compilatore sa che puoi prenderlo. Con 'Matrix &&' Non sono * that * sure- – towi

risposta

7

è necessario il esplicita std::move in questo esempio perché b non è il nome di un automatica oggetto non volatile. Riferimento 12.8 [class.copy]/p31/b1:

  • in una dichiarazione di ritorno in funzione con un tipo di classe ritorno, quando l'espressione è il nome di una automatica oggetto non volatile (parametro diverso che una funzione o prendere-clausola) con lo stesso CV- tipo qualificato come tipo di funzione di ritorno, l'operazione di copia/spostamento può essere omesso dalla creazione dell'oggetto automatico direttamente nel valore di ritorno della funzione
+2

Ah, e i riferimenti non sono oggetti. Penso che dovresti enfatizzare "oggetto" anziché "automatico" (o entrambi). – fredoverflow

+0

Penso che ** automatico ** sia il giusto \ em qui, perché traduce (all'incirca? Esattamente?) In "variabile locale". – towi

0

Non sono sicuro del motivo per cui questa funzione restituisce in base al valore. Non dovrebbe questa funzione restituire un Matrix&& come il seguente?

Matrix&& operator+(const Matrix &a, Matrix &&b) { 
    b += a; 
    return std::move(b); 
} 

Ciò ha il vantaggio che x1 + x2 + x3 + ... + xn crea al massimo un temporaneo, che è importante se Matrix sembra essere allocata pila (come poi guadagna nulla si muove).

penso che le firme devono essere come il seguente:

Matrix&& operator+(Matrix &&a,  Matrix &&b ); 
Matrix&& operator+(const Matrix &a, Matrix &&b ); 
Matrix&& operator+(Matrix &&a,  const Matrix &b); 
Matrix operator+(const Matrix &a, const Matrix &b); 
+0

No. Non si dovrebbe restituire un '&&'. Ciò significherebbe che tu restituisci un riferimento a uno degli argomenti, in cui non hai il controllo di dove proviene ("non raccogliere ciò che si trova sulla strada").Se restituisci un 'Matrix' puoi semplicemente" spostare "il contenuto da uno degli argomenti e ottieni lo stesso effetto con una performance perfetta. Inoltre, non è necessario sovraccaricare su '(&&, &&)': Il codice che scriveresti lì sarebbe lo stesso di '(&, &&)' o '(&&, &&)'. Se risparmi il sovraccarico '(&&, &&)', uno di quelli sarà selezionato dal compilatore. Hai bisogno solo di 3 sovraccarichi. – towi

+0

towi: Cosa c'è di sbagliato nel restituire un riferimento ad uno degli argomenti? Pensavo che solo restituire un riferimento a un temporaneo fosse un problema. – Clinton

+1

@towi: Inoltre, quali prove avete che il sovraccarico '(&&, &&)' non è necessario? Credo che http://ideone.com/qf3Rn mostri che è necessario. – Clinton

Problemi correlati