2011-06-11 4 views
18

estaba leyendo estos dos párrafos del FDIS (12.2p {4,5}):Cuando se crea una matriz mediante una subexpresión, ¿qué ocurre con los temporales en ella?

Hay dos contextos en los que los temporales se destruyen en un punto diferente que el final de la expresión completa. El primer contexto es cuando se llama a un constructor predeterminado para inicializar un elemento de una matriz. Si el constructor tiene uno o más argumentos predeterminados, la destrucción de cada temporal creado en un argumento predeterminado se secuencia antes de la construcción del siguiente elemento de matriz, si lo hay.

y

El segundo contexto es cuando una referencia está unido a un temporal. El temporal a la que se une la referencia o el temporal que es el objeto completo de un subobjeto a la que la referencia está obligado persiste durante toda la vida de la referencia excepto: [...]

  • A temporal unido a un parámetro de referencia en una llamada de función (5.2.2) persiste hasta la finalización de la expresión completa que contiene la llamada.

Estos dos dos parecen contradecir para el siguiente caso

struct A { 
    A() { std::cout << "C" << std::endl; } 
    ~A() { std::cout << "D" << std::endl; } 
}; 

struct B { 
    B(A const& a = A()) { } 
}; 

typedef B array[2]; 

int main() { 
    array{}; 
} 

Will esta salida CDCD como es requerido por el primer contexto, o se esta salida CCDD como es requerido por la segunda contexto? GCC parece seguir la segunda descripción de contexto y salidas CCDD. ¿He pasado por alto algo importante?


EDIT: No creo que necesite C++ 0x. Este new-expresión se ve afectada también por mi pregunta:

new array(); /* CDCD or CCDD ?? */ 

En este caso, sin embargo, GCC sigue el primer contexto y salidas CDCD.

+0

Informó, con la esperanza de que algunos comentarios de los desarrolladores de GCC en él: http://gcc.gnu.org/bugzilla/show_bug.cgi?id= 49372 –

+0

Extraño: mi GCC 4.6 no genera nada. - ah, veo que tienes el mismo comportamiento aparentemente incorrecto :) Por lo que vale: MSVS2010 SP1 saca CDCD ... – rubenvb

+0

También: 8.5.4/4 parece implicar que * normalmente * no hay restricciones de secuencia en los argumentos de una llamada. ¿Es relevante aquí, porque el caso 'new array()' en GCC imprime 'CDCD'? – rubenvb

Respuesta

2

No creo que haya una contradicción.

5.2.2 dice claramente qué es una llamada a función. Una llamada a la función es una expresión postfix seguido de paréntesis que contienen un lista posiblemente vacía, separada por comas de expresiones que constituyen los argumentos de la función .

No parece haber una llamada a la función B::B(A const&) en ningún lugar de su programa, por lo que no veo cómo se aplica el segundo pasaje.

EDITAR lo anterior es probablemente incorrecta, dado 1.9p10 etc.

+1

Aunque estoy de acuerdo en que a veces es un poco confuso, una "llamada de función" en C++ no está restringida a la sintaxis especificada en 5.2.2. Es solo la llamada de una función, que puede usar cualquier sintaxis y también puede ser implícita. Vea la nota en 1.9p15 "Varios contextos en C++ causan la evaluación de una llamada de función, aunque no aparece la sintaxis de llamada de función correspondiente en la unidad de traducción. [Ejemplo: La evaluación de una nueva expresión invoca una o más funciones de asignación y constructor; .4. ... - fin del ejemplo] ". –

+0

La mayor parte de 5.2.2 se aplica generalmente a llamadas a funciones, sin tener en cuenta el contexto que requiere la llamada de función. La viñeta que cité solo puede aplicarse cuando explícitamente se utiliza la sintaxis de llamada de función (creo que hay lugar para interpretaciones erróneas aquí, lo cual es desafortunado, especialmente debido a la referencia cruzada a 5.2.2), pero eso parecería ser extraño , porque significaría que muchos nodos de plantilla de expresión causarían un comportamiento indefinido (porque solo conservan referencias a los argumentos pasados ​​a sus constructores y los referencian mucho después de que se ejecuten sus ctors). –

+0

@ johannes Diría que de hecho hay una fraseología desafortunada, ya que de hecho hay muy poca diferencia entre una llamada de función y, por ejemplo, una invocación de operador. Pero las llamadas implícitas son diferentes. Una llamada implícita no es una expresión, por lo tanto, no forma parte de ninguna expresión completa. A veces no hay expulsión en absoluto para asociar con dicha llamada (por ejemplo, en una declaración conrltext). Así que todavía creo que el segundo contexto no se aplica. –

Cuestiones relacionadas