2011-01-18 18 views
7

En this question usuario Happy Mittal sección 12.2.5 cotizaciones de C++ 03 estándar: Un temporal ligado a un miembro de referencia en ctor-inicializador de un constructor (12.6.2) persiste hasta que el constructor sale.¿Cuál es el punto de vinculación temporal a una declaración de por vida del miembro en C++ Standard?

¿Cómo puede ser útil de todos modos? Quiero decir que una vez que el constructor sale, el temporal se destruye, pero la referencia permanece vinculada, ahora a un objeto ya destruido.

¿Cuál es el punto de especificar cuidadosamente la vida útil temporal si todavía hay una referencia colgante para toda la vida útil del objeto externo? ¿En qué escenario puede ser útil este comportamiento?

+1

Me estaba haciendo la misma pregunta. Tenga en cuenta que la redacción no se modifica en C++ 0x FCD (n3225), en 12.2 [class.temporary] nota 5. –

Respuesta

7

No es útil tener un miembro de referencia vinculado a un objeto muerto, pero es útil aclarar que la extensión de duración temporal "normal" cuando se vincula a una referencia no se aplica en este caso.

También especifica la extensión de la vida útil temporal que se aplica especialmente en el inicializador de ctor: se extiende hasta el final del ctor en lugar de morir antes de que se ejecute el cuerpo del ctor. Esto no sería útil, excepto en las clases "inteligentes" cuyo punto entero es ejecutar el ctor, y este tipo de uso (ab) se evita correctamente.

No conozco ningún ejemplo del mundo real de este último, pero me parece similar a tener destructores nothrow por defecto rompió las clases que fueron "inteligentes" en su vida y cómo fueron utilizados. Esto sí tenía usos en el mundo real y came up en discusiones sobre cómo manejar la semántica predeterminada de dtors en C++ 0x.

+0

¡Buen material en ese enlace! +1 – jweyrich

2

En lenguaje D, el proceso de construcción puede escribirse libremente en cierto grado. Sin embargo, en C++, el orden de construcción/inicialización está estrictamente estipulado. Entonces, si la inicialización de la clase requiere algún cálculo costoso, un código como a veces puede ser válido como una solución reacia.

struct S { 
    Args const &r; 
    A a; 
    B b; 
    S(args....) 
    : r(expensive_func(args....)), a(r.for_a), b(r.for_b) {} 
}; 
+1

Refactorizado para evitar el miembro de referencia y la sobrecarga probable resultante en cada instancia: 'struct SDetails {A a; B b; SDetails (Args const & r): a (r.for_a), b (r.for_b) {}}; struct S: private SDetails {S (/ * args ... * /): SDetails (expensive_func (/ * args ... * /)) {}}; ' –

+1

La refactorización es aún más fácil/mejor con C++ 0x : 'struct S {A a; B b; S (/ * args ... * /): S (expensive_func (/ * args ... * /)) {} privado: S (Args const & r): a (r.for_a), b (r.for_b) {}}; ' –

+0

Por lo tanto, en otras palabras, aunque reconozco que la inicialización a veces necesita soluciones en C++ 03, nunca usaría un miembro de referencia de esta manera. –

1

Es útil para escritores de compiladores. Ya tienen la lógica en su lugar para destruir temporales vinculados al final de un ámbito, y la salida del constructor es uno de esos puntos. Con esta regla los compiladores pueden reutilizar ese punto para destruir dichos temporales también.

Tenga en cuenta que la norma realmente debería decidir sobre algún tipo de vida, y el único otro punto razonable sería después de la lista del inicializador del ctor pero antes del cuerpo del ctor. Ese no es un punto donde los temporales se destruirían de lo contrario, y podría interferir con los bloques de función try {} catch() (que incluyen la lista de inicializadores del ctor)

+0

No cada expresión de inicialización en el inicializador de ctor ya es una expresión completa, ya que no son la subexpresión de otra expresión (C++ 03, §1.9p12)? Si es así, ya se requiere la destrucción temporal de objetos en esos puntos. Por ejemplo: 'struct A {int foo, bar; A(): foo (T(). M()), bar (T(). M()) {}}; 'Los escritores del compilador podrían fácilmente reutilizar eso (haciendo los compiladores más simples en general) a expensas de el lenguaje que permite miembros de referencia "siempre muertos". –

+0

Bueno, eso también hubiera sido posible. ¿Pero eso sería útil? Sugeriría que los peligros de un diseño así superan sus beneficios. – MSalters

+0

¿No es ese el punto? Los miembros de referencia para las extensiones extendidas de por vida * no son * útiles, incluso como se especifica actualmente, excepto en la medida en que especifiquen * algo * en lugar de dejarlo completamente ambiguo, al igual que las referencias vinculadas a los temporales en una declaración de devolución. –

Cuestiones relacionadas