2011-05-15 10 views
22

considera la siguiente función:¿Los parámetros de valor se mueven implícitamente cuando se devuelve por valor?

Foo foo(Foo x) 
{ 
    return x; 
} 

Will return x invocar el constructor de copia o el movimiento del constructor? (Vamos a dejar NRVO a un lado aquí.)

Para investigar, escribí una clase simple Foo que sólo es móvil pero no copiable:

struct Foo 
{ 
    Foo() = default; 
    Foo(const Foo&) = delete; 
    Foo(Foo&&) = default; 
}; 

Si el constructor movimiento se invoca al volver parámetros de valor por valor, toda debería estar bien. Pero la corriente compilador g ++ se queja de return x con el mensaje de error siguiente:

error: deleted function 'Foo::Foo(const Foo&)' 

Si sustituyo return x con return std::move(x), todo está bien. A partir de esto, concluyo que el cambio de los parámetros de valor debe hacerse explícitamente si se desea. ¿El comportamiento de g ++ es conforme o no?

Respuesta

24

Si hay un cursor de movimiento para Foo, se debe seleccionar.

parámetros de función están explícitamente excluidos de la elisión de la copia en sentencias de retorno (FDIS §12.9p31, primer punto):

  • en una instrucción de retorno de una función con un tipo de retorno de clases, cuando la expresión es el nombre de un objeto no volátil automática (distinto de un parámetro de función o coger-cláusula)

sin embargo, el siguiente párrafo trae explícitamente mover ctors de nuevo en consideración:

Cuando se cumplen los criterios para la elisión de una operación de copia o se cumpliría, salvo por el hecho de que el objeto de origen es un parámetro de función, y el objeto que se va a copiar se designa por un lvalue, la resolución de sobrecarga para seleccionar el constructor para la copia primero se realiza como si el objeto se designara con un valor r. ...

(El énfasis es mío en ambas citas.)

+9

Votación máxima. Este fue un cambio relativamente tardío al borrador que explica por qué aún no se implementa en todas partes. http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#1148 –

12

Este comportamiento es válida código- G ++ 's es no conforme. MSVC10 admite este comportamiento.

+0

mientras respeto su investigación, no justifica el "válido" aquí. Se reconoce que MSVC es poco estricto y permite algunos resbalones (convenientes) que el estándar prohíbe (vinculando referencias no const y funciones de miembros especializadas dentro del cuerpo de la clase, por ejemplo). –

+2

@ Matthieu: No dije que era válido * porque * MSVC10 lo admite. Es válido porque el estándar lo dice. – Puppy

+2

Lo entendí, pero todavía no hay justificación :) –

Cuestiones relacionadas