2010-11-06 21 views
8
const QPointF points[] = 
{ 
    QPointF(r.left() - i, r.top() - i), 
    QPointF(r.right() + i, r.top() - i), 
    QPointF(r.right() + i, r.bottom() + i), 
    QPointF(r.left() - i, r.bottom() + i), 
    points[0] // is this line valid (according to the C++ standard)? 
}; 

Si bien esto se compila con el compilador de MS Visual Studio, no estoy seguro de si este es un código válido de acuerdo con el estándar de C++.inicialización de matriz, está haciendo referencia a un elemento anterior ¿está bien?

Las cotizaciones de la Norma serían muy apreciadas.

+0

'g ++ -pedantic' no se queja. – kennytm

+1

... aunque no se queja de 'const int x = x;' tampoco. – kennytm

+0

Creo que es correcto (puntos [0] se refiere a un objeto válido en ese momento), pero no estoy seguro. La gramática revisa, obviamente, y hojeando Stroustroup solo dice "Una matriz se puede inicializar con una lista de valores. Puntos [0] es un valor, por lo que parece correcto. – rtpg

Respuesta

2

C++ 03/C++ 11 respuesta


No, no lo es.

En el lado derecho de la =, points sí existe pero el initialiser solamente se aplica después de que todos sus operandos han sido evaluadas.

  • Si points es al alcance de espacio de nombres (y por lo tanto tiene una duración de almacenamiento estático y ha sido cero-inicializado), entonces este es "seguro", pero su uso de points[0] se va a dar 0, en lugar de QPointF(r.left() - i, r.top() - i) nuevamente.

  • Si points tiene una duración de almacenamiento automático — que aún no se ha inicializado por lo que su uso de points[0] está intentando utilizar una variable sin inicializar, donde points[0] tiene un valor indeterminado ... lo cual es malo .

Es difícil proporcionar referencias estándar para esto, aparte de decir que no hay nada en 8.5 "Initializers" que hace que esto sea posible de manera explícita, y las reglas de llenar en otro lugar en el resto.


[n3290: 3.3.2/1]:El punto de declaración para un nombre es inmediatamente después de su completa declarador (cláusula 8) y antes de su inicializador (si existe), excepto como se indica a continuación. [Ejemplo:

int x = 12; 
{ int x = x; } 

Aquí el segundo x se inicializa con su propio (indeterminado) valor . ejemplo -end]

[n3290: 3.6.2/2]: variables con duración estática de almacenamiento (3.7.1) o de la duración de almacenamiento de hilo (3.7.2) será cero inicializada (8.5) antes de cualquier otro de inicialización se lleva a cabo. [..]

[n3290: 17.6.3.3/2]: [..] [Nota: Operaciones que implica valores indeterminados puede provocar un comportamiento indefinido. -fin nota]

+0

No me di cuenta que era una ortografía alternativa válida :) – EvilTeach

+0

@EvilTeach: ¿Qué es "eso"? –

+0

initialiser == i nitializer – EvilTeach

2

de http://www.comeaucomputing.com/pcgi-bin/compiler.cgi:

Copyright 1988-2008 Comeau Computing. All rights reserved. 
MODE:strict errors C++ C++0x_extensions 

"ComeauTest.c", line 8: warning: variable "points" is used before its value is set 
     points[0] // is this line valid (according to the C++ standard)? 
-2

viejo respuesta (no encuentra el punto):

comprobado que el actual proyecto de C++ 0x, y allí encontré la frase que dice 8.5.1.17 :

17 Las expresiones completas en un inicializador-cláusula se evalúan en en el orden en que aparecen.

Entonces, aunque esta frase no es parte del Estándar C++ de 2003, estoy bastante seguro de que esto debería funcionar en cualquier compilador actualizado, si esto es parte de C++ 0x.

Editar:
Los comentarios me hizo repensar este asunto. Esta línea solo garantiza que los objetos QPointF se crean en el orden en que ocurren en la inicialización de la matriz (relevante si los constructores del elemento tienen efectos secundarios observables). El problema es que el valor de points es indeterminado durante la inicialización de la matriz. Por lo tanto, tampoco puede haber una garantía para un valor válido de points[0], al menos no si usted confía en el estándar.

+2

No veo cómo esto es relevante en absoluto. –

+2

Correcto, aunque la evaluación debe preceder a la asignación, no dice cuándo se asignan los valores *, que es lo que importa aquí. – eudoxos

+0

@eudoxos: Sí, tiene razón, aunque se le asigna un solo valor. – smerlin

0

Puesto que no hay sequence point en la declaración, el resultado es indefinido, al igual que para el ejemplo citado en ese i=i++ página de Wikipedia.

Dicho de otro modo, nada especifica, si el compilador primero debe evaluar todo, luego asignar, o evaluar-asignar para cada elemento por separado y en qué orden.

+0

Hmm, no sé por qué no pensé en eso. Potencialmente una forma mucho más simple de describir el escenario. –

+0

Se especifica al menos el orden en que se evalúan los inicializadores para cada elemento. – smerlin

+0

@smerlin: ¿por qué crees eso?La coma en '{.., ..}' no es el "operador de coma" en este contexto. (Similar al artículo de wikipedia referenciado, subtítulo 4: "Tenga en cuenta que una llamada de función f (a, b, c) no es un uso del operador de coma y el orden de evaluación para a, b y c no está especificado. ") – eudoxos

Cuestiones relacionadas