2011-08-21 12 views
7

Hace un tiempo me dijeron que el patrón habitual para implementar operadores bianuales necesita un move final en la devolución.C++ 0x T operador + (const T &, T &&) patrón, todavía necesita mover?

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

Pero ahora no es la regla especial que en un return el compilador puede tratar el valor de retorno como temporal, y luego esto no sería necesario - sería suficiente un simple return b.

Pero, de nuevo, b tiene un nombreen esta función, por lo tanto, su lValue un - lo que dificulta que el compilador m considere que sea un trabajador temporal, y se requiere que el move.

¿Sigue siendo así en la versión más reciente del estándar C++ 0x? Necesitamos el move para implementar el patrón anterior?

+2

De acuerdo con [la respuesta] (http://stackoverflow.com/questions/6009004/are-value-parameters-implicitly-moved-when -returned-by-value/6009012 # 6009012), el 'std :: move' no es necesario. – fredoverflow

+2

Aunque podría hacer una diferencia que el parámetro sea 'Matrix &&' en lugar de 'Matrix' ... – fredoverflow

+2

It * is * complicated, yes. Y sí, creo que tienes razón. Si su parámetro a * value * como 'Matrix', entonces tiene una copia prístina para usted solo: una temperatura. El compilador sabe que puedes atraparlo. Con 'Matrix &&' No estoy * que * seguro- – towi

Respuesta

7

Se necesita el std::move explícita en este ejemplo porque b no es el nombre de un no volátil automática de objetos. Referencia 12.8 [class.copy]/p31/b1:

  • en una instrucción de retorno en una función con un tipo de retorno de clase, cuando la expresión es el nombre de un no volátil automática de objetos (parámetro otro que una función o coger-cláusula) con el mismo CV- tipo calificado como el tipo de retorno de la función, la operación de copia/mover puede omitirse mediante la construcción de la automática de objetos directamente en el valor de retorno de la función
+2

Ah, y las referencias no son objetos. Creo que deberías enfatizar "objeto" en lugar de "automático" (o ambos). – fredoverflow

+0

Creo que ** automático ** es el correcto aquí porque se traduce (¿aproximadamente? ¿Exactamente?) A "variable local". – towi

0

No estoy seguro de por qué esta función devuelve por valor. ¿No debería esta función devolver un Matrix&& como el siguiente?

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

Esto tiene la ventaja añadida de que x1 + x2 + x3 + ... + xn crea a lo sumo un temporal, lo cual es importante si la matriz pasa a ser asignado pila (ya que entonces no gana nada de movimientos).

creo que las firmas deben ser como la siguiente:

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. No debe devolver un '&&'. Esto significa que devuelve una referencia a uno de los argumentos, donde no tiene el control de dónde viene ("no recoja lo que está mintiendo en la calle").Si devuelve una 'Matriz', puede 'mover' en el contenido de uno de los argumentos y logra el mismo efecto con un rendimiento perfecto. Además, no necesita sobrecargar en '(&&, &&)': el código que escribiría allí sería el mismo que en '(&, &&)' o '(&&, &&)'. Si ahorra la sobrecarga '(&&, &&)', el compilador seleccionará uno de ellos. Solo necesitas 3 sobrecargas. – towi

+0

towi: ¿Qué hay de malo en devolver una referencia a uno de los argumentos? Pensé que solo devolver una referencia a un temporal era un problema. – Clinton

+1

@towi: Además, ¿qué evidencia tiene de que la sobrecarga '(&&, &&)' no es necesaria? Creo que http://ideone.com/qf3Rn muestra que es necesario. – Clinton

Cuestiones relacionadas