2011-12-15 10 views
16

Estoy tratando de entender la diferencia entre const ref y in, especialmente en lo que respecta al rendimiento.Diferencia entre 'const ref' y 'in'?

  1. sé que in es equivalente a const scope, pero ¿qué significa the scope stor­age class means that ref­er­ences in the pa­ra­me­ter can­not be es­caped (e.g. as­signed to a global vari­able).? código de ejemplo es bienvenido.

  2. ¿Cómo decido entre const ref y in al implementar una función? Sé con ref que el objeto no se copia porque es una referencia, pero es lo mismo con in?

Respuesta

10

1) la clase de almacenamiento scope parámetro significa que no se le permite escapar una referencia al parámetro. Ejemplo:

Object glob; 

struct S 
{ 
    Object o; 
    void foo(scope Object o) 
    { 
     this.o = o; // Not allowed! 'o' must not be escaped 
     glob = o; // ditto 
    } 
} 

Tenga en cuenta que DMD no es muy bueno para detectar esto. El ejemplo anterior actualmente compila, pero no está permitido.

scope es más útil para los parámetros de delegado:

void foo(scope void delegate() dg) 
{ 
    /* use dg */ 
} 

void main() 
{ 
    int i; 
    foo({ ++i; }); 
} 

En el ejemplo anterior, hay cierre debe ser asignado a la función anónima a pesar de que tiene upvalue porque foo "garantías" (que es el trabajo del compilador ...) que el delegado no escapó. DMD actualmente implementa esta optimización.

2) Creo que la idea es que cuando se utiliza tanto const y scope, el compilador podría pasar teóricamente por referencia o valor a voluntad, por lo que el acceso directo in es útil. DMD no aprovecha esto en este momento, pero es un atajo práctico, sin embargo, y tiene algún valor de documentación.

En resumen, in no obtendrá ningún rendimiento a menos que se utilice en un delegado. refpuede obtener algún rendimiento con estructuras grandes o matrices estáticas. Cuando se utiliza ref por motivos de rendimiento, const se usa a menudo para documentar (y hacer cumplir) que ref es y no utilizado para actualizar el valor original.

+0

1. bueno, eso explica por qué no pude reproducir el efecto. 2. Entonces, ¿estás diciendo que si un parámetro de una función tiene una clase de almacenamiento 'in', se copia? ¿Debo usar 'const ref' entonces? – Arlen

+0

Con la selección del compilador actual, todo basado en DMD, se copia. Pero lo bueno de esto es que todavía está técnicamente definida la implementación porque el usuario no puede notar la diferencia. Para que DMD aproveche esto para la optimización, primero debe implementar el 'scope'. Si ha identificado la copia como un cuello de botella y desea optimizar, usar 'const ref' es una buena idea. –

+0

¿Cómo sabes tanto sobre DMD? ¿Eres uno de los core-devs? – Arlen

10
  1. No es legal para scope parámetros para eludir la función. Se supone que el compilador garantiza que ninguna referencia a esos datos escapa a la función. Se usa principalmente con delegados, ya que permite al compilador evitar asignar un cierre, ya que sabe que el delegado no escapará.

  2. const ref es const - al igual que in sería - pero la variable se pasa por referencia en lugar de la copia, por lo que evitar una copia. Sin embargo, a diferencia de C++const ref hace no trabajo con valores. Es debe recibir un lvalue. Por lo tanto, si declara que un parámetro es const ref, limitará lo que puede pasarle. En general, tendrá que declarar una variable para pasarla, mientras que in aceptará una temporal.

    void func(const ref int var) {} 
    int a; 
    func(a); //legal 
    func(7); //illegal 
    

Ambas llamadas sería legal si func tomó const o in. Entonces, en general, la pregunta no es si debe usar const ref o in. La pregunta es si debe usar const o in. Y en ese caso, la pregunta es si desea usar scope o no, ya que ambos son const. Y utiliza scope si desea asegurarse de que ninguna referencia a la variable que pase escapará de esa función, por lo que generalmente solo se usa con delegados, pero podría ser útil con clases o matrices.

Sin embargo, pure en una función garantiza que no hay referencias a cualquiera de sus argumentos pueden escapar, excepto a través del valor de retorno (ya pure funciones sólo se pueden utilizar variables globales si son inmutables o son tipos de valor y son const), por lo pure generalmente le ofrece todo lo que necesita para los parámetros que son clases y matrices. Además, si el tipo de devolución es una clase o matriz, en general no desea hacerlo para que los argumentos no puedan escapar, porque en lugar de poder reutilizar nada de esos argumentos en el valor de retorno, la función se ve obligado a hacer una copia, que generalmente es menos eficiente.

Por lo tanto, scope generalmente solo se usa con delegados, pero en ocasiones es útil con clases o matrices. En general, ya es preferible que las funciones sean pure, por lo que se ocupa de la mayor parte del problema. Por lo tanto, aunque no hace daño usar in, a menudo no tiene mucho sentido usar in en lugar de const. Y generalmente solo usa const ref si realmente desea evitar copiar la variable que se está transfiriendo, porque de lo contrario solo puede pasar lvalues ​​a esa función. Usted puede sobrecargar una función tal que tiene una versión que toma const y una que toma const ref, pero que obviamente resulta en duplicación de código, así que a menos que realmente desee const ref, probablemente sea mejor usar const.

scope todavía no se ha implementado para otra cosa que los delegados (a partir del 06.18.2013), por lo que usar ya sea scope o in con delegados que no sea nada está mal aconsejado: editar

. Por el momento, son engañosas, y si/una vez scope se implementa para algo más que delegados, existe un alto riesgo de que su código se rompa debido a las referencias a las variables marcadas con scope o in escapando.

+0

¿No es cierto que 'in' no funciona como debería porque' scope' no está completamente implementado en DMD? ¿No sería un cambio radical una vez que 'scope 'se implemente por completo para aquellos que han usado' in' incorrectamente? – Arlen

+0

Suponiendo que 'scope' tiene errores (y puede que sea así, no lo uso demasiado, así que no estoy exactamente seguro de su estado actual), entonces sí, sería un cambio radical para cualquier código que usó 'scope' o' in' incorrectamente, pero eso es lo mismo con prácticamente cualquier error del compilador. Afortunadamente, el número de estos problemas en dmd ha disminuido significativamente debido al rápido ritmo de desarrollo desde que se cambió a github, pero aún es posible encontrar problemas en los que una característica no se implementa correctamente. –

+0

'scope' no es realmente defectuoso, simplemente no está implementado en absoluto a excepción de una optimización. 'pure' rara vez es una buena alternativa al' scope' porque con una función de miembro 'pure', aún puede escapar del parámetro asignándolo a un campo de miembro, y' pure' tiene otras restricciones no relacionadas. Si 'scope' se implementó por completo, sería útil para una gran cantidad de casos, como ser capaz de pasar de forma segura rebanadas para apilar la memoria a una función que la recibe con' scope'. –

Cuestiones relacionadas