2011-05-22 8 views
19

Estuve estudiando las referencias de rvalue últimamente y llegué a la conclusión de que es bastante ventajoso usar el valor de paso en todas partes donde se realizará la copia completa de un objeto (para una justificación completa, por ejemplo, How to reduce redundant code when adding rvalue reference operator overloads? y Want speed? Pass by value!), porque el compilador puede optimizar automáticamente una copia en casos como f(std::move(a));, donde f se define como void f(A a);.¿Los compiladores usan automáticamente la semántica de movimiento cuando un objeto movible se usa por última vez?

Una consecuencia negativa de pasar por valor en todas partes es que todo el código se convierte en desorden con std::move incluso en casos simples, tales como:

void Object::value(A a) 
{ 
    value_ = std::move(a); 
} 

Obviamente, si escribía solamente el siguiente:

void Object::value(A a) 
{ 
    value_ = a; 
} 

no debería ser difícil para el compilador reconocer que a está cerca del final de su vida útil, incluso sin la pista y no me penaliza con copia adicional. De hecho, el compilador debería ser capaz de reconocer esto incluso en funciones complejas.

Las preguntas:

  1. ¿Es esta optimización permitido por el 0x estándar de C++?

  2. ¿Los compiladores lo emplean? Incluso en casos complejos, es decir, la función consiste en más de una línea.

  3. ¿Cuán confiable es esta optimización, es decir, puedo esperar que el compilador la utilice tanto como espero que el compilador aplique la optimización del valor de retorno?

+4

"use pass-by-value en todas partes" - Por favor, ** no haga esto **. Solo hazlo si haces una copia del parámetro dentro de la función de todos modos, ¡no solo en todas partes! – Xeo

+0

@ jons34yp ¿no es mejor pasar siempre por constante referencia? –

+0

@Yet: Es mejor juzgar para cada caso lo que mejor se adapte. –

Respuesta

16

¿Es esta optimización permitido por el 0x estándar de C++?

¿Los compiladores lo emplean? Incluso en casos complejos , es decir, la función se compone de más de una línea?

¿Qué tan confiable es esta optimización, es decir, puedo esperar que el compilador utilizar tanto como espero que el compilador aplicar Valor devuelto optimización?

Usted debe decorar A(const A&) y A(A&&) con declaraciones de impresión y ejecutar los casos de prueba de su interés. No olvide probar los argumentos de lvalue si esos casos de uso son parte de su diseño.

Las respuestas correctas dependerán de qué tan costosas sean la copia y el movimiento de A, cuántos argumentos tiene realmente Object::value y cuánta repetición de código está dispuesto a soportar.

Finalmente, sea muy sospechoso de cualquier directriz que contenga palabras como "always" o "everywhere". P.ej. Yo uso goto de vez en cuando. Pero otros programadores tienen palabras como "nunca" asociadas con goto. Pero de vez en cuando, no puede vencer a goto tanto en velocidad como en claridad.

Habrá momentos en los que deberías preferir un par de foo(const A&) foo(A&&) sobre foo(A). Y veces no lo harás Tus experimentos con miembros decorados de copia y movimiento te guiarán.

+0

No veo por qué no. Tenemos que crear un modelo de ejecución * en algún lugar *, y creo que en ese modelo encontraremos que no tiene sentido mantener un valor después de su último uso. Ergo, si es el último uso y el último uso es asignación/inicialización, podemos moverlo en lugar de copiarlo. Esto sería sin pérdida porque en nuestro modelo el movimiento nunca es más costoso que el copiado, y el movimiento está destinado a transferir un valor. (Es decir, opera bajo el principio de si ...) – GManNickG

+2

Es difícil definir el "último uso". Incluso con la definición que tenemos actualmente, es posible detectar la optimización de movimiento implícito (y por lo tanto, realmente no es una optimización). Pero se alcanzaron compromisos. Lo que ayudó a alcanzar esos compromisos fue vincularlo a la optimización del valor de retorno (que también es detectable). Ejemplo: ponga un 'B b (a);' antes de su "último uso". Ahora, si te mueves de 'a',' b. ~ B() 'puede detectar el movimiento almacenando una referencia a' a'. –

Cuestiones relacionadas