2010-04-30 13 views
5
int* test() 
{ 
    int a = 5; 
    int* b = &a; 
    return b; 
} 

¿El resultado de test ser un bad pointer? Por lo que yo sé, una debe ser eliminada y luego b se convertiría en un puntero desordenado, ¿verdad?C++: Punteros y alcance

¿Qué hay de las cosas más complicadas, no un puntero int pero lo mismo con una clase con 20 miembros más o menos?

+2

No hay recolección de basura aquí. Solo apilate desenrollando. – Tom

Respuesta

7

El término para lo que está devolviendo es un "dangling pointer". a es una variable local asignada en la pila, y ya no está disponible una vez que sale del alcance (que es algo completamente diferente de la recolección de basura). Intentar utilizar el resultado de una llamada al test() será un comportamiento indefinido.

Por otro lado, si usted no asignó a en la pila - (int *a = new int(5);), entonces int *b = a; return b; estaría muy bien, aunque no es tan bueno como return new int(5). Sin embargo, si no hace correctamente el resultado free más tarde, tendrá una pérdida de memoria.

+0

Bien, ¿hay alguna forma de resolver esto?¿Para que el valor persista, así que no tengo que definirlo en otro lugar? –

+0

¿Cuál es exactamente tu objetivo? ¿Devolviendo un puntero al mismo objeto cada vez que se llama 'test()'? Podría devolver la dirección de una variable estática, por ejemplo. –

5

Sí, es un puntero a algo que ya no existe, la variable local llamada a. Si a es un int, una matriz, una instancia de una clase no hace diferencia. Y C++ no tiene recolección de basura.

En este caso, como en muchos otros, usted debe, por supuesto, devolver una copia:

int test() 
{ 
    int a = 5; 
    return a; 
} 

Esto es cierto para las clases, así como la incorporada en los tipos.

2

En este caso, el puntero b apunta a una entidad asignada desde la pila. Esa memoria estará disponible para el proceso de llamada tan pronto como esta función regrese.

Si necesita crear un objeto que sobrevivirá al proceso que lo creó, tendrá que utilizar malloc() o new para obtener un bloque de memoria del montón, y recordar a free o delete más tarde.

0

Sí, esto dará un puntero colgante. Si desea que el valor persista, tiene un par de posibilidades. Una de ellas es que, como aparentemente desea devolver un valor, haga exactamente eso: devuelva el valor en lugar de un puntero. Otra es asignar el objeto involucrado con new y devolver un puntero a ese espacio dinámicamente asignado. Esto hace que eliminar el objeto sea responsabilidad de la persona que llama, sin embargo, lo que puede provocar fugas de memoria y cosas por el estilo.

Al final, generalmente quiere averiguar qué ámbito realmente necesita la variable, y que sea propiedad de algo (con más frecuencia un objeto) con ese alcance, por lo que se creará automáticamente al ingresar al alcance, y se destruye automáticamente al salir del alcance.

Si no puede hacer eso, aún necesita averiguar quién es el "propietario" del objeto y será responsable de destruirlo según sea necesario. De vez en cuando es difícil precisar, y necesita algo como un puntero de referencia para realizar un seguimiento de las cosas. Al menos en mi experiencia, estos se usan mucho más a menudo de lo que realmente deberían ser. He estado escribiendo C++ casi tanto como cualquiera fuera de AT & T, y aún no he necesitado un shared_ptr. Algunas veces, pensé que lo necesitaría, pero eventualmente descubrí que un diseño más limpio eliminaba el requisito.

+0

Puede insertar punteros compartidos en sistemas anteriores que pueden hacer cosas inesperadas, y que no desea rediseñar, y obtener una cantidad significativa de seguridad. Además, son más fáciles de mantener correctos durante años de modificación. –

+0

@David: Ah, es cierto, no quise dar a entender que fueran inútiles ni nada de eso. Al mismo tiempo, tiendo a pensar en ellos como más una curita que cómo se escribe realmente el código * debe *. No hay duda, sin embargo, de que si tienes código que está "sangrando" la memoria, una tirita puede ser extremadamente útil ... –

+0

Básicamente son recolección de basura, de un tipo bastante primitivo y descentralizado. Son útiles en cualquier lugar donde se recoja basura, y para sistemas grandes de la vida real, prefiero depender del GC que de todos los desarrolladores que trabajaron en él en los últimos diez años. –