Orden de evaluación en los parámetros de la función C ++


90

Si tenemos tres funciones (foo, bar y baz) que están compuestas así ...

foo(bar(), baz())

¿Existe alguna garantía por parte del estándar C ++ de que la barra se evaluará antes que baz?

Respuestas:


102

No, no existe tal garantía. No está especificado según el estándar C ++.

Bjarne Stroustrup también lo dice explícitamente en "El lenguaje de programación C ++" sección 6.2.2 de la tercera edición, con algún razonamiento:

Se puede generar un mejor código en ausencia de restricciones en el orden de evaluación de expresiones

Aunque técnicamente esto se refiere a una parte anterior de la misma sección que dice que el orden de evaluación de las partes de una expresión tampoco está especificado, es decir

int x = f(2) + g(3);   // unspecified whether f() or g() is called first

Puedo aceptar esta respuesta en 8 minutos ... ¡supongo que me quedaré un poco!
Clark Gaebel

4
Sí, pero un mejor código podría ser ESCRITO (= más limpio) si el orden de evaluación de la expresión fuera ESTRICTO, que generalmente es mucho más importante que la generación de código. Vea este ejemplo: stackoverflow.com/questions/43612592/… Entonces ahí, Stroustrup.
Bill Kotsias

1
Si el pedido es importante, puede realizar la secuenciación usted mismo. Hacer lo contrario siempre implicaría un costo por algo que no siempre (¿rara vez?) Importa. Creo que la política de no pagar por lo que no usas es lo único en lo que están de acuerdo la mayoría de los programadores de C ++.
tweej

3
¿No debería ser "comportamiento no especificado" en lugar de "indefinido"?
GoodDeeds

1
@ChrisDodd rechazar una respuesta aceptada debido al uso de la palabra "indefinido" frente a "no especificado" me parece una pedantería maliciosa ... No dije que esto sea un "comportamiento indefinido", y de lo contrario "indefinido" y "no especificado" parecen ¿sinónimo? En cualquier caso, proponer una edición de la respuesta habría sido una forma más productiva de discutir esto
Eli Bendersky

21

Desde [5.2.2] Llamada a función,

El orden de evaluación de los argumentos no se especifica. Todos los efectos secundarios de las evaluaciones de expresiones de argumentos entran en vigor antes de que se ingrese la función.

Por lo tanto, no hay garantía de que bar()se ejecutará antes baz(), solo eso bar()y baz()se llamará antes foo.

También tenga en cuenta de [5] Expresiones que:

excepto donde se indique [por ejemplo, reglas especiales para &&y ||], el orden de evaluación de los operandos de operadores individuales y subexpresiones de expresiones individuales, y el orden en el que se producen los efectos secundarios, no se especifica.

por lo que incluso si preguntaba si bar()se ejecutará antes baz()en foo(bar() + baz()), el orden aún no está especificado.


4
Un ejemplo de una "nota especial" de [5.14] Operador lógico AND: "A diferencia &, &&garantiza la evaluación de izquierda a derecha: el segundo operando no se evalúa si el primer operando lo es false".
Daniel Trebbien

20

No hay un orden específico para bar () y baz (); lo único que dice el Estándar es que ambos serán evaluados antes de que se llame a foo (). Del estándar C ++, sección 5.2.2 / 8:

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


4
El hecho de que se evalúen antes que foo () es un poco tranquilizador, al menos.
Bill Kotsias

1
@BillKotsias El estándar también dice que las llamadas a funciones no pueden superponerse (es decir, una implementación no puede ejecutar la línea 1 de bar, luego la línea 1 de baz, luego la línea 2 de bar, etc.), lo cual también es bueno. :-)
melpomene


3

En C ++ 11, el texto relevante se puede encontrar en 8.3.6 Argumentos predeterminados / 9 (énfasis mío)

Los argumentos predeterminados se evalúan cada vez que se llama a la función. El orden de evaluación de los argumentos de la función no está especificado . En consecuencia, los parámetros de una función no se utilizarán en un argumento predeterminado, incluso si no se evalúan.

El estándar C ++ 14 también usa la misma verborrea, y se encuentra en la misma sección .


0

Como ya han señalado otros, la norma no proporciona ninguna orientación sobre el orden de evaluación para este escenario en particular. Este orden de evaluación se deja entonces al compilador, y el compilador puede tener una garantía.

Es importante recordar que el estándar C ++ es realmente un lenguaje para instruir a un compilador en la construcción de código ensamblador / máquina. El estándar es solo una parte de la ecuación. Cuando el estándar sea ambiguo o esté específicamente definido por la implementación, debe recurrir al compilador y comprender cómo traduce las instrucciones de C ++ al verdadero lenguaje de máquina.

Por lo tanto, si el orden de evaluación es un requisito, o al menos importante, y ser compatible con el compilador cruzado no es un requisito, investigue cómo su compilador finalmente ensamblará esto, su respuesta podría estar ahí. Tenga en cuenta que el compilador podría cambiar su metodología en el futuro

Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.