2011-03-12 11 views
14

¿Se permite el compilador a eliminar la copia que se requiere para la captura de valor bajo?C++ 0x: Capture By Value for Lambda, siempre una copia?

vector<Image> movie1; 
apply([=movie1](){ return movie1.size(); }); 
  • ¿Hay alguna circunstancia de que el compilador no necesita copiar movie1?
    • Tal vez si el compilador pudiera saber que apply en realidad no cambiomovie1?
    • ¿O es útil que Lambdas sea por defecto const funtores en cualquier caso?
  • ¿Ayuda en absoluto que vector tiene un constructor movimiento y movimiento asignar?
    • En caso afirmativo, ¿es necesario agregarlos a Image también, para evitar una copia costosa aquí?
  • ¿Hay alguna diferencia en el mecanismo de cómo y cuándo se requiere una copia de por valor de captura comparación con argumentos por valor? p.ej. void operate(vector<Image> movie)?

Respuesta

9

Estoy bastante seguro de que no se puede.

Incluso si la función externa ya no usa explícitamente la variable, mover la variable cambiaría la semántica de la destrucción.

Tener constructores de movimiento para Image no ayuda, vector puede o swap sin mover sus elementos.

Si la variable es de solo lectura a partir de ahora, ¿por qué no capturar por referencia? Incluso podría crear una referencia constante y capturar eso.

Si la variable no es de solo lectura, se requiere la copia. No importa si la función externa o la lambda realiza la modificación, el compilador no puede permitir que esa modificación sea visible para la otra.

La única diferencia que veo entre por valor de captura y argumento por valor pasando es que la captura se nombra, no puede ser un temporal. Por lo tanto, no se pueden usar las optimizaciones de aprobación de argumentos aplicables a los temporales.

+0

"¿por qué no capturar por referencia"? Estoy en el proceso de entender todas las implicaciones. Estoy de acuerdo. "La única diferencia ..." es una gran respuesta. ¡Perfecto! – towi

3

Hay siempre la regla "como si". Siempre que se vea como si se hubieran seguido las reglas, el compilador puede hacer lo que quiera. Entonces para los objetos donde el constructor de copia y el destructor no tienen efectos secundarios, y donde no se realizan cambios en la copia, o el objeto original no se accede después (para que nadie se dé cuenta si hacemos cambios en el objeto), el compilador podría probar que la eliminación de la copia es legal bajo la regla "como si".

Pero aparte de eso, no, no puede simplemente eliminar la copia, como dijo @Ben. Las reglas de elisión de copia "regular" no cubren este caso.

+0

Ese es el término que estaba buscando: * copia elisión *. Gracias por aclarar que estos no se pueden aplicar aquí. Gracias. – towi

+0

La elisión de copia no es aplicable aquí, ya que se introdujo la elisión de copia para situaciones en las que efectivamente "mueve" el valor (ya no se puede acceder al valor original; esto es cierto tanto para inicialización de copia como para devolución). En el caso de lambda puede acceder al valor capturado tanto en el lambda como en el contexto original, por lo tanto, es una copia verdadera. – Suma

Cuestiones relacionadas