2010-07-15 10 views
9

Una pregunta básica que no estoy seguro de la respuesta. Es la siguiente función válida?C++ referencia de devolución/memoria de la pila

std::vector<int> & test_function() { 
    std::vector<int> x; 

    // do whatever 

    return x; 
} 

Si es así, ¿por qué? ¿No debería el programa eliminar x de la pila después de que la función retorna? Gracias.

Respuesta

11

El comportamiento no está definido. No debe devolver referencias a variables locales.

+1

¡Maldita sea, pásame! – Anthony

+1

El código que se muestra no contiene (por sí solo) ningún comportamiento indefinido. El UB pasaría en otro código que llama a esta función. –

8

La función está bien formada (sintácticamente correcta), pero tan pronto como la función retorna, la referencia devuelta no es válida y no se puede usar.

Para aclarar: el código en cuestión hace no invoca cualquier comportamiento indefinido. Puede llamar de forma segura esta función, siempre y cuando no se utiliza el valor de retorno, por ejemplo, esto es válido:

test_function(); // ok 

Sin embargo, si se intenta utilizar el valor de retorno (es decir, inicializar otra referencia con ella o copia el referente en otro objeto), entonces invocará un comportamiento indefinido debido a que el tiempo de vida del referente (el objeto x) habrá terminado (x serán destruidos cuando la función devuelve porque es una variable automática):

std::vector<int>& vec = test_function(); // undefined 
std::vector<int> vec = test_function(); // undefined 
+0

En una nota seria, si la estructura a la que se hace referencia es solo un montón de POD (sin punteros) o es una primitiva, si se mantiene el marco de pila normal, y se copia el valor (no se guarda una referencia a él, entonces su segundo ejemplo aquí), el valor local original estará bien inmediatamente después de la devolución ('mov esp, ebp; pop ebp;' marco de pila local no se altera). Los destructores, sin embargo, son invocados y los datos pueden ser manipulados/cambiados. Sin embargo, esta es la forma incorrecta de hacer esto y predecir lo que sucederá, incluso si se adivina con precisión en un lugar no es portátil. –

+0

@jMerliN: Incluso para un objeto de tipo POD, los resultados están formalmente indefinidos. La duración de un POD finaliza cuando finaliza su duración de almacenamiento; para una variable local, esto es en el punto en que la función regresa. El uso de un objeto una vez finalizado su ciclo de vida produce un comportamiento indefinido. ¿Esto posiblemente "funciona" en la práctica con objetos tipo POD? Quizás, pero como dices, no es un comportamiento en el que se debe confiar. –

+0

Definitivamente no se debe confiar cuando multihebra se convierta en estándar ya que la ubicación del marco de pila que ya pudo haber sido reutilizado por otro hilo (Tenga en cuenta que el estándar no define cómo se implementan la pila o el montón). –

0

No puede devolver una referencia a una variable local por el mismo motivo por el que no puede devolver un poi nter a una variable local, porque a la vuelta de la función esas variables locales se desasignan y, por lo tanto, la referencia o el puntero deja de ser válido.

2

Sí, es válido, pero si intenta utilizar el valor devuelto, obtendrá un comportamiento indefinido.