2010-09-23 27 views
6

Esto es lo que he codificado hoyllamada de función en orden incorrecto

#include <iostream> 
using namespace std; 

int function1() 
{ 
    cout<<"hello from function1()"; return 0; 
} 

int function2() 
{ 
    cout<<"hello from function2()"; return 0; 
} 

int main() 
{ 
    int func_diffresult = 0; 
    func_diffresult = function1() - function2(); 
    cout<<func_diffresult; /** prints 0 correctly **/ 
} 

la salida es conseguir es hello from function2()hello from function1(). Creo que la salida debería ser hello from function1()hello from function2(). ¿Mi compilador está jugando conmigo?

+0

Presumiblemente tiene un error tipográfico en el código allí ... Veo dos declaraciones 'function1'. – dmckee

+1

¡Esto no compilaría le falta la segunda función! Cambie el nombre de la segunda función a function2(). – Secko

+0

@dmckee corrigió el error de tipeo. – Raghvan

Respuesta

10

El orden de evaluación de los argumentos del operador - es unspecified. Entonces las funciones pueden ser llamadas en cualquier orden.

5

El operador - se convierte efectivamente en operator-(function1(), function2()), y el orden de evaluación de los parámetros de la función deliberadamente no se especifica.


notas relacionadas:

Una muy buena razón para dejar sin especificar es manejar de manera eficiente convenciones de llamada. Por ejemplo, la convención de llamadas C requiere que los parámetros se inserten en la pila en el orden inverso.

Por lo tanto, tiene sentido evaluar las funciones en orden inverso ya que el resultado se puede presionar inmediatamente. Evaluar los parámetros de izquierda a derecha y luego presionar los resultados de derecha a izquierda implica almacenar todos los resultados antes de presionar alguno de ellos. Si realmente necesita hacer esto, puede hacerlo manualmente. Si no le importa, el beneficio de rendimiento probablemente sí lo haga.

+0

Eso es cierto para 'cdecl' en x86, pero no todas las convenciones de llamadas introducen valores en la pila. Algunos de ellos pasan argumentos en los registros. – dan04

+0

Absolutamente. Es por eso que el orden es "no especificado" en lugar de "de derecha a izquierda" (o "de izquierda a derecha"), y ¿quién sabe qué convenciones de llamadas se usarán en el futuro? Es mejor decir "no confíe en la orden de evaluación de coincidencia de orden de parámetros" y permita que los compiladores lo hagan de la manera más eficiente posible. – Zooba

2

Las normas ISO no garantizan el orden en que se evaluarán las subexpresiones.

Desde el ++ 0x proyecto de norma c:


1,9. Ejecución del programa:
          :
13/ Secuenciado antes es un transitivo, relación asimétrica, por pares entre las evaluaciones ejecutadas por un solo hilo, que induce un orden parcial entre dichas evaluaciones. Dadas dos evaluaciones A y B, si A se secuencia antes de B, entonces la ejecución de A debe preceder a la ejecución de B. Si A no se secuencia antes de que B y B no se secuencian antes de A, entonces A y B no se siguen. [Nota: La ejecución de evaluaciones no secuenciadas de puede solaparse.]

Las evaluaciones A y B se secuencian de forma indeterminada cuando A se secuencia antes de que B o B se secuencian antes que A, pero no se especifica qué. [Nota: Las evaluaciones indeterminadamente secuenciados no pueden superponerse, pero o bien podrían ser ejecutados en primer lugar.]
          :
15/ Excepto donde se indique, las evaluaciones de los operandos de los operadores individuales y de subexpresiones de expresiones individuales se no secuenciado
          :
Cuando se llama a una función (si o no la función es en línea), cada efecto del valor de cálculo y secundarios asociados con cualquier expresión argumento, o con la expresión de sufijo que designa la función llamada, se secuenciaron antes de la ejecución de cada expresión o declaración en el cuerpo de la función llamada [Nota al pie: en otras palabras, las ejecuciones de funciones no se entrelazan entre sí]. [Nota: los cómputos de valor y los efectos secundarios asociados con diferentes expresiones de argumentos no se han secuenciado.]
Cada evaluación en la función de llamada (incluidas otras llamadas a funciones) que no está secuenciada específicamente antes o después de la ejecución del cuerpo del llamado la función está indeterminadamente secuenciada con respecto a la ejecución de la función llamada.


En otras palabras, la implementación es libre de organizar las llamadas utilizando el método que desee. Sin embargo, las llamadas a funciones se tratan especialmente según la nota al pie: hacen y no entrelazado.

+0

Simplemente curioso: ¿Significa que la función1 y la función2 también se pueden intercalar (y por lo tanto ejecutar paralelamente) en una arquitectura de CPU múltiple? – Chubsdad

+0

Supongo que sí. Debido a que el término estándar para A antes de B, o B antes de A, pero no especificado es 'secuencia indeterminada'. Pero dado que el Estándar dice 'No Secuenciado', IMO, significa que las llamadas a la función también pueden intercalarse. – Chubsdad

+0

@Chubsdad: sí, vea la actualización (oración final y nota al final del primer párrafo de ** 13 **, y segundo párrafo completo de ** 13 **). Para no secuenciado, pueden superponerse. Para la secuencia indeterminada, todavía están secuenciados (sin solapamiento), pero podría ir AB o BA. La pregunta se refiere a una operación no secuenciada por lo que podría superponerse. – paxdiablo

Cuestiones relacionadas