2010-12-31 20 views
16

Lo que sucede cuando se tiene el siguiente código:C++ puntero del alcance

void makeItHappen() 
{ 
    char* text = "Hello, world"; 
} 

¿El text salir del alcance y se eliminan automáticamente o permanece en la memoria?

Y qué pasa con el siguiente ejemplo:

class SomeClass 
{ 
    public: 
     SomeClass(); 
     ~SomeClass(); 
}; 

SomeClass::SomeClass() { } 
SomeClass::~SomeClass() 
{ 
    std::cout << "Destroyed?" << std::endl; 
} 

int main() 
{ 
    SomeClass* someClass = new SomeClass(); 
    return 0; 
} // What happend to someClass? 

hace lo mismo ocurre aquí?

Gracias!

Respuesta

22
char* text = "Hello, world"; 

Aquí una variable automática (un puntero) se crea en la pila y configurar para que apunte a un valor en memoria constante, lo que significa: existe

  • la cadena literal en "" a través de la ejecución del programa completo.
  • usted no es responsable de "asignarlo" o "liberarlo"
  • no puede cambiarlo. Si desea cambiarlo, debe asignar una "memoria no constante" y copiarla allí.

Cuando el puntero sale del alcance, se libera el puntero de la memoria (4 bytes) y la cadena sigue en el mismo lugar: memoria constante.

Para este último:

SomeClass* someClass = new SomeClass(); 

Entonces someClass puntero también serán liberados cuando se sale del ámbito (ya que el propio puntero está en la pila también, sólo en el primer ejemplo) ... pero no el objeto!

La palabra clave new básicamente significa que se puede asignar algo de memoria para el objeto en tienda libre - y eres responsable de llamar a delete en algún momento con el fin de liberar esa memoria.

+0

@Kos: ¿Esto significa que el número 2 en 'int x = 2;' también existe a través de la ejecución del programa completo? –

+1

La diferencia es que el número 2 no necesita tener una dirección en la memoria, y la cadena sí (como apunta el puntero). * (Este número 2 existe en algún lugar de la sección de códigos de su memoria, que no necesita acceder directamente, porque es, bueno, el código, no los datos). * – Kos

+0

@Kos Gracias por una gran respuesta ! Pero, ¿de qué sirve mantener '" Hello, world "' en la memoria? – Kevin

11

¿El text salir del alcance

Sí! Es local para la función makeItHappen() y cuando la función lo devuelve queda fuera del alcance. Sin embargo, el literal de cadena apuntado "Hello, world"; tiene una duración de almacenamiento estático y se almacena en la sección de solo lectura de la memoria.

Y qué pasa con el siguiente ejemplo:

......
hace lo mismo ocurre aquí?

Su segundo ejemplo de código pierde la memoria.

SomeClass* someClass = new SomeClass();

someClass es local a main() así que cuando vuelve principales que siendo una variable automática se destruye. Sin embargo, el objeto apuntado permanece en la memoria y no hay forma de liberarlo después de que la función regrese. Debe escribir explícitamente delete someClass para desasignar correctamente la memoria.

+1

+1 "el literal apuntado a la cadena" Hola, mundo "; tiene duración de almacenamiento estático" –

+0

Pierde memoria porque no ha eliminado el objeto que creó. –

6

El texto variable sale del ámbito (sin embargo, el literal de cadena no se elimina).

Para los objetos que asigne con nuevos (como su SomeClass), debe eliminarlos explícitamente. Si desea que los objetos asignados como este se eliminen automáticamente, eche un vistazo a boost smart pointers (std :: unique_ptr si su compilador tiene conocimiento de C++ 0x).

Esto eliminará automáticamente el objeto asignado cuando el puntero compartido salga del ámbito.

Su código sería el siguiente aspecto:

int main(int argv, char **argv) 
{ 
    boost::scoped_ptr<SomeClass> ptr(new SomeClass); 
    // the object is automatically deleted 
    return 0; 
} 

Nota: En este ejemplo particular, también se puede utilizar std :: auto_ptr (pero esto será obsoleto en C++ 0x).

Nota 2: Como se señaló en los comentarios de Kos, en este caso es más apropiado utilizar boost :: scoped_ptr o std :: unique_ptr (C++ 0x). Mi respuesta usó por primera vez boost :: shared_ptr, que es más apropiado si necesita compartir la propiedad de un puntero entre varias clases, por ejemplo.

+0

Habría +1 ... pero luego noté que mencionó los punteros de recuento de referencias, cuando la herramienta más adecuada es 'std :: unique_ptr' de C++ 0x /' boost :: scoped_ptr'/'std: : auto_ptr'. Esos son los responsables de eliminar el objeto cuando el puntero sale del alcance, y exactamente para eso. – Kos

+0

@Kos: Tiene toda la razón en que en este caso particular unique_ptr es más apropiado. Voy a hacer un cambio ... – villintehaspam

+0

+1 a continuación. :) (¿Es ese último enlace shared_ptr dejado intencionalmente?) – Kos

1

En el primer ejemplo, el literal de cadena se almacena en el segmento de datos de su ejecutable.
En el segundo caso, no tiene que llamar al delete (en su programa de ejemplo simplemente termina) ya que al finalizar el programa, el montón se libera de todos modos para el proceso.
Tenga en cuenta que hay sistema operativo (como he leído) que tiene que liberar explícitamente montón incluso si el programa finaliza, ya que no se limpiará en la terminación para usted.
Por supuesto, el programador es responsable de la administración de la memoria en C++ y los objetos que crea en el montón deben ser delete ed una vez que no sean necesarios.