Si tenemos tres funciones (foo, bar y baz) que se componen así…
foo(bar(), baz())
¿Existe alguna garantía por parte del estándar C++ de que la barra se evaluará antes que la baz?
Si tenemos tres funciones (foo, bar y baz) que se componen así…
foo(bar(), baz())
¿Existe alguna garantía por parte del estándar C++ de que la barra se evaluará antes que la baz?
Eli Bendersky
No, no hay tal garantía. No está especificado según el estándar C++.
Bjarne Stroustrup también lo dice explícitamente en la sección 6.2.2 de la tercera edición de “El lenguaje de programación C++”, con algún razonamiento:
Se puede generar 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
Sí, pero se podría ESCRIBIR un código mejor (= 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, Stroustrup.
– Bill Kotsias
25 de abril de 2017 a las 13:57
Si el orden es importante, puede hacer la secuencia usted mismo. De lo contrario, siempre incurriría en 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 la mayoría de los programadores de C++ están de acuerdo.
– tweej
2 de diciembre de 2017 a las 9:53
¿No debería ser “comportamiento no especificado” en lugar de “indefinido”?
– Buenas acciones
6 de enero de 2018 a las 19:38
@GoodDeeds Anterior C ++ 17, comportamiento indefinido si las funciones causan efectos secundarios en la misma ubicación de memoria. Publicar C ++ 17 no está especificado.
– Transeúnte
22 de junio de 2018 a las 16:53
@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 es un “comportamiento indefinido”, y de lo contrario parece “indefinido” y “no especificado” ¿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
20 de julio de 2018 a las 13:19
daniel trebbin
Desde [5.2.2] Llamada de función,
No se especifica el orden de evaluación de los argumentos. Todos los efectos secundarios de las evaluaciones de expresiones de argumento surten efecto antes de que se ingrese la función.
Por lo tanto, no hay garantía de que bar()
correrá antes baz()
sólo eso bar()
y baz()
será llamado antes foo
.
También nota de [5] Expresiones que:
excepto donde se indique [e.g. special rules for
&&
and||
]no se especifica el orden de evaluación de los operandos de los operadores individuales y las subexpresiones de las expresiones individuales, ni el orden en que se producen los efectos secundarios.
así que incluso si estuvieras preguntando si bar()
correrá antes baz()
en foo(bar() + baz())
el orden aún no está especificado.
Un ejemplo de una “nota especial” de [5.14] Operador lógico AND: “A diferencia de &
, &&
garantiza la evaluación de izquierda a derecha: el segundo operando no se evalúa si el primer operando es false
.”
– Daniel Trebbien
29 de mayo de 2010 a las 12:31
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:
No se especifica el orden de evaluación de los argumentos.
El hecho de que se evalúen antes que foo() es un poco tranquilizador, al menos.
– Bill Kotsias
25 de abril de 2017 a las 13:58
@BillKotsias El estándar también dice que las llamadas a funciones no se pueden superponer (es decir, una implementación no puede ejecutar la línea 1 de bar
entonces la línea 1 de baz
entonces la línea 2 de bar
, etc.), que también es agradable. 🙂
– melpomene
31 de julio de 2019 a las 21:04
C++17 especifica el orden de evaluación de los operadores que no se especificaba hasta C++17. Consulte la pregunta ¿Cuáles son las garantías de orden de evaluación introducidas por C++17? Pero nota tu expresión
foo(bar(), baz())
todavía tiene un orden de evaluación no especificado.
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 palabrería, y se encuentra en la misma sección.
Programador erudito
Como ya han señalado otros, el estándar no brinda ninguna orientación sobre el orden de evaluación para este escenario en particular. Este orden de evaluación se deja luego 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 sólo una parte de la ecuación. Cuando el estándar es ambiguo o está específicamente definido por la implementación, debe recurrir al compilador y comprender cómo traduce las instrucciones de C++ a un verdadero lenguaje de máquina.
Entonces, si el orden de evaluación es un requisito, o al menos importante, y la compatibilidad entre compiladores no es un requisito, investigue cómo su compilador finalmente ensamblará esto, su respuesta finalmente podría estar allí. Tenga en cuenta que el compilador podría cambiar su metodología en el futuro