2012-09-22 30 views
9

La norma no especifica el orden de evaluación de los argumentos con esta línea:¿Por qué el orden de evaluación para los parámetros de función no se especifica en C++?

El orden de evaluación de argumentos no se especifica.

Lo que

mejor código puede ser generado en ausencia de restricciones a la orden de evaluación expresión

implica?

¿Cuál es el inconveniente de pedir a todos los compiladores que evalúen los argumentos de la función De izquierda a derecha, por ejemplo? ¿Qué tipo de optimizaciones realizan los compiladores debido a esta especificación no especificada?

+4

Permitir que el compilador reordene la evaluación de los operandos agrega más espacio para la optimización. – Mysticial

+1

@Mysticial: por absurda que parezca, debería ser una respuesta, ¡y en realidad la respuesta * aceptada *! –

+0

¿Qué tipo de optimizaciones realizan los compiladores? – unj2

Respuesta

25

Permitir que el compilador reordene la evaluación de los operandos agrega más espacio para la optimización.

Aquí hay un ejemplo completamente inventado con fines ilustrativos.

Supongamos que el procesador puede:

  • Edición 1 instrucción cada ciclo.
  • Ejecute una adición en 1 ciclo.
  • Ejecuta una multiplicación en 3 ciclos.
  • Puede ejecutar adiciones y multiplicaciones al mismo tiempo.

Ahora suponga que tiene una llamada a la función de la siguiente manera:

foo(a += 1, b += 2, c += 3, d *= 10); 

Si se va a ejecutar esta izquierda a derecha en un procesador sin OOE:

Cycle - Operation 
0  - a += 1 
1  - b += 2 
2  - c += 3 
3  - d *= 10 
4  - d *= 10 
5  - d *= 10 

Ahora bien, si permitir que el compilador los reordene: (y comience la multiplicación primero)

Cycle - Operation 
0  - d *= 10 
1  - a += 1, d *= 10 
2  - b += 2, d *= 10 
3  - c += 3 

Entonces 6 ciclos contra 4 ciclos.

De nuevo, esto está completamente ideado. Los procesadores modernos son mucho más complicados que eso. Pero se entiende la idea.

1

Aquí hay un ejemplo simple. Suponga que tiene una llamada a la función de la siguiente manera:

// assume that p is a pointer to an integer 
foo(*p * 3, bar(), *p * 3 + 1); 

El compilador necesita eliminar la referencia p dos veces (y hacer algunos cálculos basados ​​en el resultado) y llamar bar vez. Si el compilador es inteligente, puede cambiar el orden de la evaluación a

int temp = *p * 3; 
foo(temp, bar(), temp + 1); 

De esta manera se tiene que hacer el "eliminar la referencia, se multiplica por 3" sólo una vez. Esto se conoce como eliminación de subexpresiones comunes.

+1

Para ser justos, incluso los idiomas que garantizan el orden de evaluación pueden hacerlo, siempre que puedan probar que el valor de 'p' no puede cambiar entre ellos. Por supuesto, con el modelo de memoria C que es casi imposible de garantizar, que es probablemente la razón por la cual el orden de evaluación indefinido es necesario para lograr esta optimización. – Joey

Cuestiones relacionadas