2010-09-01 12 views
7

¿Está bien devolver una referencia a una variable local desde una función? Por local quiero decir que la variable se crearía (en la pila, es decir, sin usar nueva) dentro de la función y su alcance está dentro de esa función solamente. Obtuve respuestas contradictorias cuando busqué sobre esto. 1) dice que el tipo de uso es correcto pero 2) lo contradice.pregunta sobre la función que devuelve una referencia en C++

1) http://functionx.com/cpp/examples/returnreference.htm
2) http://www.cprogramming.com/tutorial/references.html (bajo Referencias & sección Seguridad)

¿Cuál de ellas es la correcta?

Otra pregunta que tuve, si 1) es correcta, son las siguientes para el mismo propósito.

i) int & a = func();
ii) int a = func(); donde func() devuelve una referencia a una int (variable local en esa función).

En los dos casos anteriores, no hay copia del valor de retorno involucrado no es así. Me gustaría evitar la copia de valores devueltos ya que el valor de retorno podría ser grande.

Gracias de antemano.

Raghava.

+7

no tengo idea de lo que la primera referencia que tienes está tratando de hacer, aparte de propagar errores a través del código C++. No confíes en eso –

+0

posible duplicado de http://stackoverflow.com/questions/1465851/returning-const-reference-to-local-variable-from-a-function –

+1

El enlace (1) es definitivamente erróneo. Enlace (2) No vi el cambio por referencia. –

Respuesta

6

Como dice todo el mundo, no haga eso. Devolver una referencia o puntero a una variable local siempre es incorrecto, porque el acto de devolver se deshace de la variable local y, por lo tanto, la referencia o el puntero se invalida automáticamente.

copia puede no ser un problema. Los compiladores de C++ pueden omitir los constructores de copia cuando regresan de las funciones (la "optimización del valor de retorno"), por lo que un compilador suficientemente inteligente podría construir el valor en su lugar. Por lo tanto, es posible que pueda devolver un gran valor sin ninguna copia. Pruébalo y mira; puede colocar declaraciones de salida temporalmente en el constructor de copia (si ha escrito una y no está utilizando la generada automáticamente) para ver si realmente se llama.

Por lo tanto, sin ejecutar e intentar, no sabe si hay una copia real y, de ser así, qué tan problemático es. Como siempre, programe una hora y un perfil para ver si hay un problema y, de ser así, dónde. Hacer cualquier cosa arriesgada y/o confusa para acelerar el rendimiento casi nunca vale la pena antes de cronometrar y perfilar.

5

Si se refiere a una variable interna de la función, no ... siempre es una tontería devolver una referencia. Devolver una referencia a una variable miembro de una función miembro está perfectamente bien.

En cuanto a querer evitar la copia de estructuras de datos grandes. Espere hasta que tenga datos reales del perfil que demuestren que está a) haciendo una copia, yb) que en realidad es un cuello de botella. "La optimización prematura es la raíz de todos los males", puede ser un poco extrema, pero la optimización prematura ciertamente causa mucho dolor y problemas, mientras que rara vez, si es que alguna vez, proporciona CUALQUIERA de los beneficios que esos intentos deben lograr.

+0

Sí, quise decir una variable interna (local) para la función. Editaría mi publicación para ser más específico. – Raghava

6

Puede devolver una referencia a una variable local estática en una función. De lo contrario, es una receta para el desastre porque la variable local se destruye una vez que la función retorna.

Following puede ser útil que toma el mismo ejemplo que citó en su primera referencia.

EDIT 2:

Para el punto II en su mensaje, supongamos un 'fn' función como se muestra

int& fn(){ 
static int x; 
return x; 
} 

int a = fn(); 

Esto implica una copia del valor izquierdo de la 'fn' expresión.

No se trata de una copia, si era

int &a = fn(); 
+0

@chubsdad: Gracias por el enlace. Básicamente es la misma pregunta que hice aquí e incluso el cartel apunta al mismo enlace que mencioné. – Raghava

2

Nunca es aceptable para devolver una referencia a la variable local no estático de una función. La variable sale del alcance cuando la función retorna y, por lo tanto, la referencia se referirá a un objeto destruido.

Si bien esto puede parecer que 'funciona' en el primer ejemplo proporcionado en 1), esta mala práctica rápidamente comenzará a fallarle con las clases que tienen un destructor o son más grandes.

Lo mejor es devolver un puntero, devolver una referencia a un objeto estático local, devolver una referencia a una variable miembro.

En este caso, si el objeto se construye dentro de la función que se va a devolver, puede considerar la implementación de la semántica del movimiento C++ 0x en su clase grande. Esto podría convertir una 'copia grande' en algunos intercambios de punteros.

+1

Con "return a pointer", supongo que se refiere a un puntero a un objeto dinámicamente asignado. Devolver un puntero a una variable de función local tiene exactamente el mismo problema que devolver una referencia. –

+0

Y con "return a pointer", supongo que se refiere a un objeto RAII * que contiene * un puntero.;) En cuanto a la implementación de la semántica de movimientos, supongo que te refieres a IFF, observas que la copia realmente ocurre y también la observas, lo que causa un cuello de botella. –

+0

@Noah: la copia definitivamente se produciría si es una devolución por valor ¿no? – Raghava

4

Los ejemplos que se ven en su primer enlace son totalmente falsas. Esa página en functionx.com es basura. Devolver una referencia a una variable local (automática) siempre es un error, ya que cualquier intento de acceder al valor devuelto dará como resultado un comportamiento indefinido.

El segundo enlace lo hace bien.

+0

Gracias por la respuesta. – Raghava

0

asumiendo que func devuelve una referencia a un valor que vive después del retorno de la función (estática local o global), entonces su

i) int& a = func(); 
ii) int a = func(); where func() returns a reference to an int (local variable in that function). 

son bastante diferentes

en (i) un alambique se refiere a el estático o global. Chaning un cambiará la variable original

en (ii) a es una copia local, el cambio no tiene ningún efecto sobre la variable original