2012-04-17 19 views
9

tengo este código (versión simplificada):¿Una referencia vinculada a un parámetro de función prolonga la vida útil de ese temporal?

const int& function(const int& param) 
{ 
    return param; 
} 

const int& reference = function(10); 
//use reference 

Estoy totalmente no puede decidir en qué medida estándar de C++ 03 $ 12.2/5 redacción

El temporal para el que la referencia está obligado o el temporal que es el objeto completo de un subobjeto del cual el límite temporal persiste durante el tiempo de vida de la referencia ...

es aplicable aquí.

¿Hay reference variable en el código anterior válido o pendiente? ¿La referencia en el código de llamada prolongará el tiempo de vida del temporal pasado como el parámetro?

Respuesta

9

A expresión completa es una expresión que no es una subexpresión de otra expresión. En este caso, la expresión completa que contiene la llamada function(10) es la expresión de asignación:

const int& reference = function(10); 

Para llamar function con el argumento de 10, un objeto const-referencia temporal se crea al objeto entero temporal 10. La duración del entero temporal y la referencia constante const se extienden a través de la asignación, por lo que aunque la expresión de asignación sea válida, intentar usar el entero al que hace referencia el reference es Undefined Behavior como reference ya no hace referencia a un objeto activo.

El estándar de C++ 11, creo, aclara la situación:

El temporal a la que se une la referencia o el temporal que es el objeto completo de un subobjeto en que la referencia está obligado persiste durante la vida útil de la referencia, excepto:

...

- un temporal ligado 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.

EDIT: "El temporal a la que se une la referencia ... persiste durante toda la vida útil de la referencia". En este caso, la duración de la referencia finaliza al final de la expresión de asignación, al igual que la duración del entero temporal.

2

Esto compilará, pero terminará con una referencia colgante. param se libera después de function devuelve.

  1. función es llamada con una referencia al objeto temporal, anónimo
  2. función devuelve la referencia
  3. ahora que la función ha devuelto el parámetro temporal se libera
  4. la referencia está colgando como el objeto era destruido

Si lo hizo no const, entonces no se habría compilado porque no puede pasar una referencia no constante a un objeto anónimo.

+0

¿No se destruye 'param' al final de la tarea? "Los objetos temporales se destruyen como el último paso en la evaluación de la expresión completa (1.9) que (léxicamente) contiene el punto donde se crearon". –

1

es esta parte que es importante

El temporal para el que la referencia está obligado

En este caso, el parámetro está ligado a la temporal, y serán destruidos después de la llamada.

No se puede extender aún más la vida pasando la referencia en.

+1

No puede negar que su 'referencia' está vinculada a la temporal. De hecho, hay varias referencias relacionadas con el temporal. El estándar está muy mal redactado aquí. La intención es, por supuesto, que la vida útil solo se extienda para coincidir con la referencia inicializada con el temporario real. Lamentablemente, eso no es realmente lo que dice el estándar. –

+2

@JamesKanze: Estoy de acuerdo en que la redacción no es muy precisa, pero una vez dicho esto, con un modelo de compilación separado, sería imposible para el compilador saber que la vida del temporal debería extenderse en el sitio de llamada después de la función completa. El compilador no puede saber si la referencia devuelta está vinculada al mismo objeto que el parámetro o cualquier otro objeto (es decir, 'const int & function (const int &) {static int i = 0; return i;}') –

+0

Esta respuesta no. t abordar cualquier cosa ... y el temporal se destruye en el punto y coma al final de la declaración, no inmediatamente después de la llamada. – Potatoswatter

2

Desde el C++ 11 Viepoint una referencia devuelto por una función es no temporal:

12.12.1 Temporaries de tipo de clase se crean en diferentes contextos: la unión hace referencia a un prvalue (8.5.3), devolviendo un valor pr (6.6.3), una conversión que crea un valor pr (4.1, 5.2.9, 5.2.11, 5.4), lanzando una excepción (15.1), ingresando un controlador (15.3), y en algunas inicializaciones (8.5).

Una función que devuelve una referencia dosn't return prvalue ("pure rvalue"), por lo que no es temporal. Esto parece muy natural: compilador no puede gestionar toda la vida de los objetos referenciados, es responsabilidad del programador

Por lo tanto, el compilador no proporciona ningún guarantes liftime de referencia const int & ya que no se limita al temporal.

+0

... y este es un lugar donde C++ 11 fijado redacción ambigua de C++ 03, una solución que debe ser tomado para aplicar con carácter retroactivo. – Potatoswatter

Cuestiones relacionadas