2010-12-06 7 views
19

¿Hay alguna buena razón para que operator = no sea un punto de secuencia? Ambos en C y C++.¿Hay alguna buena razón por la cual el operador de asignación no es un punto de secuencia?

Tengo problemas para pensar en un contraejemplo.

+0

Eso requeriría que el compilador calcule el LHS antes que el RHS. ¿Por qué querrías crear ese tipo de restricción? –

+2

'a = b = c = 0;' – pmg

+7

En general, las cosas necesitan una razón para ** ser ** un punto de secuencia. No necesitan una razón ** no ** para ser un punto de secuencia; ese es el predeterminado. –

Respuesta

20

Por encargo:

En general, las cosas necesitan una razón para ser un punto de secuencia. No necesitan una razón no para ser un punto de secuencia; ese es el predeterminado.

Por ejemplo, && debe ser un punto de secuencia debido a un comportamiento de cortocircuito: si el lado izquierdo es falsa, el lado derecho no debe ser evaluado. (Esto no se trata solo de optimización, el lado derecho podría tener efectos secundarios, y/o depender de que el lado izquierdo sea verdadero, como en el ptr && ptr->data). Por lo tanto, el lado izquierdo debe evaluarse primero, antes que el derecho lado de la mano, para ver si el lado derecho debería ser evaluado en absoluto.

Este motivo no existe para = porque, aunque hay una "evaluación" para ambos lados (aunque existen diferentes restricciones sobre lo que puede aparecer en ambos lados: el lado izquierdo debe ser un valor l - l no significa "izquierda", por cierto, significa "ubicación", como en la ubicación en la memoria - no podemos asignar a un temporal o un literal), no importa qué lado se evalúa primero - siempre y cuando ya que ambos lados son evaluados antes de la asignación real.

+3

+1, pero '=' no ser un punto de secuencia me mordió una vez: tenía 'myArray [i ++] = ;', y uno de los dos compiladores calculó el RHS "después" del LHS, produciendo el respuesta incorrecta. Mi culpa al final, pero difícil, no obstante. –

+0

IIRC y FWIW, Java ofrece más garantías aquí :) –

+0

El comportamiento de cortocircuito por sí solo no requeriría un punto de secuencia. Una expresión como '(((ch = * x ++)! = 0) && (* y ++ = ch))' podría, * pero para el requisito explícito de que && impone un punto de secuencia *, demora el incremento de x hasta después de la ejecución de la segunda parte de la expresión, ya que el compilador podría determinar antes de incrementar x si el operando de la izquierda de '&&' evaluaría o no a cero. En la práctica, es poco probable que cualquiera de los reordenamientos del código prohibidos por el punto de la secuencia sea útil, pero en algunos casos teóricos podrían serlo. – supercat

0

Es (más o menos). El operador = (que puede ser definido por el ingeniero (también conocido como el operador definido por el usuario = para tipos de clase)) es simplemente azúcar sintáctica para una llamada a función. Como resultado, tiene la misma semántica de "punto de secuencia" que una llamada a función.

Si estamos utilizando tipos incorporados, entonces creo que es algo bueno.
No desea introducir demasiados puntos de secuencia ya que esto dificulta las optimizaciones.

+2

Es solo azúcar sintáctico para una llamada de función para clases definidas por el usuario en C++. Aunque de alguna manera insinúas eso, no está nada claro por la forma en que lo redactaste. –

+6

'"punto de secuencia" semántica "que no son particularmente útiles, porque los argumentos para' operator = 'serán LHS y RHS del signo' = ', y las llamadas a funciones no imponen orden en la evaluación de sus argumentos: solo la evaluación de la función en sí misma es un punto de secuencia. –

0

Hay muchas razones para no requerir que ninguno de los lados se evalúe antes que el otro. Una pregunta más interesante es si la evaluación de ambas partes, completa con los efectos secundarios, debería ser requerida antes de que el operador de asignación haga algo. Sugeriría que tal requisito aliviaría algunas restricciones de aliasing pero en algunos casos requieren más trabajo para un compilador. Por ejemplo, supongamos que "foo" y "bar" son punteros para estructuras grandes cuyas direcciones se superpondrían. La declaración "* foo = * bar;" representaría un comportamiento indefinido bajo el estándar actual. Si hubiera un punto de secuencia entre la evaluación de los operandos y la asignación, se garantizaría que dicha afirmación "funcione". Dicha garantía requeriría más complicado para el operador de asignación, requiriendo un código más grande y más lento, incluso si en la práctica los punteros nunca se superpondrán.

Ejemplo:

 
unsigned char foo[100]; 
typedef struct {int x, int y;} POINT; 
POINT *p1 = (POINT*)foo; 
POINT *p2 = (POINT*)(&(p1->y)); 

Teniendo en cuenta las declaraciones anteriores, creo que las siguientes declaraciones tienen los comportamientos definidos estrictamente indicados y no implican ningún comportamiento indefinido.

 
    p1->y = somevalue; // Sets p2->x to somevalue 
    p2->x = somevalue; // Sets p1->y to somevalue 
    *p1 = mystruct;  // Sets p2->x to mystruct.y 
    *p2 = mystruct;  // Sets p1->x to mystruct.x 

los dos siguientes declaraciones, sin embargo, implicaría un comportamiento indefinido:

 
    *p1 = *p2; 
    *p2 = *p1; 

Si hubiera un punto de secuencia en el signo de igualdad, un compilador tendría que o bien comparar p1 y p2, o de lo contrario copie el operando fuente a una ubicación temporal y luego cópielo al destino. El estándar, sin embargo, deja en claro que las dos declaraciones anteriores son consideradas como Comportamiento Indefinido. El estándar requiere que los compiladores generen código que funcione correctamente al copiar una estructura a una estructura que no se superpone, pero que no restringe lo que los compiladores pueden hacer si las estructuras se superponen. Un compilador que convertiría el procesador en un bucle enviando "Reglas de Frink". cada socket TCP abierto no violaría el estándar al hacerlo.

+0

"_large structures cuyas direcciones se superpondrían ._" ¿Puedes dar un ejemplo? – curiousguy

+0

Obtuviste la frase "reglas de Frink" del episodio de Homer 3D de "Los Simpson", ¿verdad? – ninjalj

+0

@curiousguy: ver ejemplo. – supercat

Cuestiones relacionadas