Foros del Web » Programación para mayores de 30 ;) » C/C++ »

[SOLUCIONADO] Mi cadena se pierde

Estas en el tema de Mi cadena se pierde en el foro de C/C++ en Foros del Web. hola amigos, tengo un problema, y es que cuando pruebo este programa, la salida del destructor de mi objeto "cadenita" al mostrar el dato miembro ...
  #1 (permalink)  
Antiguo 30/05/2014, 23:02
Avatar de GumiCat  
Fecha de Ingreso: mayo-2014
Ubicación: Argentina
Mensajes: 16
Antigüedad: 10 años, 5 meses
Puntos: 0
Mi cadena se pierde

hola amigos, tengo un problema, y es que cuando pruebo este programa, la salida del destructor de mi objeto "cadenita" al mostrar el dato miembro cad, me muestra un montón de simbolos raros en vez de mostrar la última cadena que se le asignó, que debería ser "adios".

Alguien sabe porqué pasa esto? dejo mi programa

Código C++:
Ver original
  1. #include <iostream>
  2. #include <new>
  3. #include <cstring>
  4.  
  5. using std::cout;
  6.  
  7. class cadena
  8. {
  9.     public:
  10.         cadena();
  11.         cadena(const char *);
  12.         ~cadena();     
  13.     private:
  14.         char * cad;
  15. };
  16.  
  17. cadena::cadena(){
  18. }
  19.  
  20. cadena::cadena(const char *LCad)
  21. {  
  22.     cad = new char[strlen(LCad) + 1];
  23.     strcpy(cad, LCad);
  24.     cout << "Constructor de " << cad << "\n";
  25. }
  26.  
  27. cadena::~cadena()
  28. {
  29.     cout << "Destructor de " << cad << "\n";
  30.     delete [] cad;
  31. }
  32.  
  33.  
  34. int main()
  35. {
  36.     cadena cadenita("Hola");
  37.     cadenita = "Adios";
  38.    
  39.     return 0;
  40. }
  #2 (permalink)  
Antiguo 31/05/2014, 05:43
Avatar de vangodp  
Fecha de Ingreso: octubre-2013
Mensajes: 934
Antigüedad: 11 años, 1 mes
Puntos: 38
Respuesta: Mi cadena se pierde

La verdad no tengo ni idea pero estas decindo que imprima cadena y cadena ya no existe asi que creo que el compilador ya no sabe como tomar eso te lo imprime cosas raras por que ya no tiene ni tipo ni valor.

lo malo que veo a tu código es que creo que estas cometiendo un error.
Mira este constructor bien...
Código C++:
Ver original
  1. cadena::cadena(const char *LCad)
  2. {  
  3.     cad = new char[strlen(LCad) + 1];
  4.     strcpy(cad, LCad);
  5.     cout << "Constructor de " << cad << "\n";
  6. }
ahora fiate en main.
Código C++:
Ver original
  1. int main()
  2. {
  3.     cadena cadenita("Hola");
  4.     cadenita = "Adios";
  5.    
  6.     return 0;
  7. }
sa salida es:
Código txt:
Ver original
  1. Constructor de Hola
  2. Constructor de Adios
  3. Destructor de ÿ↕:
  4. Destructor de ÿ↕:
  5.  
  6. Process returned 0 (0x0)   execution time : 0.083 s
  7. Press any key to continue.

Si llamas a este constructor: cadena cadenita("Hola");
Estas haciendo: cad = new char[strlen(LCad) + 1];
Estas creando un espacio en memoria y asignandolo a cad ¿correcto?...
Luego llamas otra vez al constructor aquí: cadenita = "Adios";
Por lo que otra vez haces: cad = new char[strlen(LCad) + 1];

O sea creas 2 espacios de memoria y los asignas a cad. Solo los liberas al final cuando termina main es cuando se llama los destructores.

¿No crees que antes de llamar al constructor por segunda vez deberías liberar la memoria?
Te lo digo por que a mi me parece que estas teniendo fuga de memoria. No estoy seguro 100% pero me parece que tras un new debes llamar un delete si pretendes asignar una nueva variable en el heap a cad, y debes liberar la variable anterior antes. Es solo impresión mía o no lo se, a ver si alguien mas lo confirma.
Cuidado con eso :O

Creo que debes llamar al destructor antes de llamar al constructor nuevamente pero ahi tendrias que crear un nuevo objeto, lo mejor seria hacer una función que liberase la memoria antes de llamarlo nuevamente.

Última edición por vangodp; 31/05/2014 a las 05:49
  #3 (permalink)  
Antiguo 31/05/2014, 09:43
 
Fecha de Ingreso: septiembre-2010
Mensajes: 494
Antigüedad: 14 años, 1 mes
Puntos: 10
Respuesta: Mi cadena se pierde

Ampliando la respuesta de vangodp, y con las sugerencias que te ha dado, has de implementar el constructor copia.
  #4 (permalink)  
Antiguo 31/05/2014, 11:24
Avatar de GumiCat  
Fecha de Ingreso: mayo-2014
Ubicación: Argentina
Mensajes: 16
Antigüedad: 10 años, 5 meses
Puntos: 0
Respuesta: Mi cadena se pierde

Modifiqué mi programa para que cuando ya haya memoria asignada, entonces se libere y ponga a "cad" en NULL, pero aún así no me está funcionando.
¿Qué estoy haciendo mal?

Código C++:
Ver original
  1. #include <iostream>
  2. #include <new>
  3. #include <cstring>
  4.  
  5. using std::cout;
  6.  
  7. class cadena
  8. {
  9.     public:
  10.         cadena(const char *);
  11.         ~cadena();     
  12.     private:
  13.         void estableceCadena(const char *);
  14.        
  15.         char * cad;
  16.        
  17. };
  18.  
  19. cadena::cadena(const char *LCad)
  20. {  
  21.     cad = NULL;
  22.    
  23.     cout << "Constructor de: " << LCad << "\n";
  24.     estableceCadena(LCad);
  25. }
  26.  
  27. cadena::~cadena()
  28. {
  29.     cout << "Destructor de " << cad << "\n";
  30.    
  31.     delete [] cad;
  32.     cad = NULL;
  33. }
  34.  
  35. void cadena::estableceCadena(const char *Cad2)
  36. {
  37.     if (cad != NULL) //si ya hay memoria asignada
  38.     {
  39.         delete [] cad; //borramos la cadena
  40.         cad = NULL; // y hacemos que no apunte a nada
  41.     }
  42.    
  43.     cad = new char[strlen(Cad2) + 1]; //reasignamos un espacio de memoria
  44.     strcpy(cad, Cad2);   //copiamos
  45. }
  46.  
  47. int main()
  48. {
  49.     cadena Cad1("Hola");
  50.     Cad1 = "Adios";
  51.    
  52.     return 0;
  53. }

esta es la salida de mi programa

Código texto:
Ver original
  1. Constructor de: Hola
  2. Constructor de: Adios
  3. Destructor de Adios
  4. Destructor de ↑'=
  5.  
  6. << El programa ha finalizado: codigo de salida: 0 >>
  7. << Presione enter para cerrar esta ventana >>
  #5 (permalink)  
Antiguo 31/05/2014, 12:20
Avatar de vangodp  
Fecha de Ingreso: octubre-2013
Mensajes: 934
Antigüedad: 11 años, 1 mes
Puntos: 38
Respuesta: Mi cadena se pierde

a ver me parece que no estas entendiendo...

sabes como trabaja los constructores y destructores?
Te lo explico por si las moscas.
el constructor llamas al crear la funcion

Pero los destructores se llaman automáticamente cuando main finaliza.
o sea que solo liberas la variable en memoria cuando termina main
entonces mira eso:

si hago tipo * variable = new tipo

que es lo que estoy haciendo?

1º estas creando un puntero tipo * variable
despues le estas asignando un entero en el heap variable = new tipo

con que pongas NULL no estas liberando memoria.... es mas ahora mismo es cuando ya no la puedes liberar por que la perdiste.

solo liberas memoria llamando a delete.

para poder usar el puntero pprimero llamas delet variable y después variable = NULL;

sino realmente lo has empeorado mas aun XD

crear:
int * p = new int;

borrar:
delet p;

p = NULL;

ahora ya puedes hacer otra vez

p = new int;

Y otra cosa es que esta claro que si llamas al constructor 2 veces

cadena::~cadena()
{
cout << "Destructor de " << cad << "\n";
delete [] cad;
}

cadena::~cadena()
{
cout << "Destructor de " << cad << "\n";
delete [] cad;
}

que va pasar?

como se trata de la misma variable la primera ves va imprimir cout << "Destructor de " << cad << "\n"; y lo va destruir delete [] cad;

luego llamas una vez mas y cuando imprimes cout << "Destructor de " << cad << "\n";
la variable ya esta destruida por que se trata de la misma variable.

mejor usas funciones para cambiar el valor a cad por segunda vez por que no le veo necesidad de que llamas al constructor 2 veces.

ya llamas una vez cuando crea pues haz una función que cambia eso y que antes de cambiar llama al delet[] cad para liberar ;)

A ver si llegamos a afinar ;)
  #6 (permalink)  
Antiguo 31/05/2014, 13:43
 
Fecha de Ingreso: septiembre-2010
Mensajes: 494
Antigüedad: 14 años, 1 mes
Puntos: 10
Respuesta: Mi cadena se pierde

A la sugerencia anterior de que implementes el constructor copia, añado el prototipo.
Código C++:
Ver original
  1. cadena &operator = (const cadena& c);

A ver si ahora te animas a ello
Piensa en qué está haciendo el programa en esta línea:
Código C++:
Ver original
  1. cadenita = "Adios";
  #7 (permalink)  
Antiguo 31/05/2014, 14:14
 
Fecha de Ingreso: junio-2008
Ubicación: Seattle, USA
Mensajes: 733
Antigüedad: 16 años, 5 meses
Puntos: 61
Respuesta: Mi cadena se pierde

Lo que se ve es la consecuencia de hacer un alias.

El destructor no se está ejecutando 2 veces para el mismo objeto, ni tampoco se necesita implementar el constructor de copia, sino el operator de asignacion. En la instrucción

cadenita = "Adios"

es este operator el que se está usando.

Al no haber un operador de asignacion implementado explicitamente se provee del mismo implicitamente que copia miembro a miembro.

Como hay un puntero al interior de la definicion de la clase, cada objeto tiene uno, al copiar miembro a miembro se produce un alias, luego al destruirse uno de los 2 objetos (al usar delete) el puntero guardado en el otro queda apuntando a una zona que el primero liberó, que es lo que se aprecia en la salida del programa.
__________________
Visita mi perfil en LinkedIn
  #8 (permalink)  
Antiguo 31/05/2014, 14:19
 
Fecha de Ingreso: septiembre-2010
Mensajes: 494
Antigüedad: 14 años, 1 mes
Puntos: 10
Respuesta: Mi cadena se pierde

Cita:
Iniciado por CalgaryCorpus Ver Mensaje
Lo que se ve es la consecuencia de hacer un alias.

....................ni tampoco se necesita implementar el constructor de copia, sino el operator de asignacion.
A veces pienso que hay poco rigor en algunas respuestas, y ahora soy yo el que peco de ello. Igualmente me refería al operador de asignación, no al constructor copia.

Ahora soy yo el que voy a inmolarme un rato.
  #9 (permalink)  
Antiguo 31/05/2014, 14:33
Avatar de GumiCat  
Fecha de Ingreso: mayo-2014
Ubicación: Argentina
Mensajes: 16
Antigüedad: 10 años, 5 meses
Puntos: 0
Respuesta: Mi cadena se pierde

Aaah, ya sé donde metí la pata en el nuevo código ya me quedo más claro.

Ahora, evité usar un operador sobrecargado de asignacion = para punteros a cadenas, porque estoy aprendiendo de un libro en el cual no usan uno de esos e invocan directamente al constructor a través de una conversión implícita.

Según el libro hace al programa más rápido.
Bueno, gracias por explicármelo más detalladamente
  #10 (permalink)  
Antiguo 31/05/2014, 20:50
Avatar de vangodp  
Fecha de Ingreso: octubre-2013
Mensajes: 934
Antigüedad: 11 años, 1 mes
Puntos: 38
Respuesta: Mi cadena se pierde

Cita:
El destructor no se está ejecutando 2 veces para el mismo objeto
Calgary quizas nos quieras explicar mejor por que cres que no se esta llamando el destructor 2 veces para el mismo objeto si al final aparece 2 veces.
A ver que explicación pones tu en esto..

Código txt:
Ver original
  1. Constructor de: Hola
  2. Constructor de: Adios
  3. Destructor de Adios
  4. Destructor de ↑'=
  5.      
  6. << El programa ha finalizado: codigo de salida: 0 >>
  7. << Presione enter para cerrar esta ventana >>

Destructor de Adios
Destructor de ↑'=


si el destructor no sale 2 veces... a lo mejor soy yo que veo doble XD

Cita:
Iniciado por GumiCat Ver Mensaje
Aaah, ya sé donde metí la pata en el nuevo código ya me quedo más claro.

Ahora, evité usar un operador sobrecargado de asignacion = para punteros a cadenas, porque estoy aprendiendo de un libro en el cual no usan uno de esos e invocan directamente al constructor a través de una conversión implícita.

Según el libro hace al programa más rápido.
Bueno, gracias por explicármelo más detalladamente
Pues si has encontrado la solución pues ponla aquí para que mas personas la vean. mira que..

Última edición por vangodp; 31/05/2014 a las 21:09
  #11 (permalink)  
Antiguo 01/06/2014, 04:33
 
Fecha de Ingreso: junio-2008
Ubicación: Seattle, USA
Mensajes: 733
Antigüedad: 16 años, 5 meses
Puntos: 61
Respuesta: Mi cadena se pierde

En ese codigo hay 2 objetos.
Lo que ves es la ejecucion del destructor de 2 objetos distintos, no la ejecucion del destructor de 1 solo objeto 2 veces.

La asignacion crea un objeto temporal (fijarse en que TAMBIEN se esta ejecutando 2 constructores)
__________________
Visita mi perfil en LinkedIn
  #12 (permalink)  
Antiguo 01/06/2014, 05:01
Avatar de vangodp  
Fecha de Ingreso: octubre-2013
Mensajes: 934
Antigüedad: 11 años, 1 mes
Puntos: 38
Respuesta: Mi cadena se pierde

Pues que raro eso :S
  #13 (permalink)  
Antiguo 01/06/2014, 05:30
 
Fecha de Ingreso: junio-2008
Ubicación: Seattle, USA
Mensajes: 733
Antigüedad: 16 años, 5 meses
Puntos: 61
Respuesta: Mi cadena se pierde

No lo es. Los objetos temporales existen y el compilador tiene la obligacion de crearlos.

Lo raro sería que un objeto se construyera o destruyera 2 veces.
Es posible jugar con el destructor, pero los codigos aqui vistos no son ejemplo de esto.

Tal vez es mas evidente que existen 2 objetos imprimiendo el valor del puntero this.

Código C++:
Ver original
  1. #include <iostream>
  2. using namespace std;
  3.  
  4. class MiClase {
  5.    public: MiClase( const char* s ) {
  6.       cout << "Construyo " << s << " -- " << this << endl;
  7.    }
  8.  
  9.    public: ~MiClase() {
  10.       cout << "Destruyo " << this << endl;
  11.    }
  12. };
  13.  
  14. int main() {
  15.    cout << "Antes de construccion" << endl;
  16.    MiClase m("[CONSTRUCTOR]");
  17.  
  18.    cout << "Despues de construccion, antes de copia" << endl;
  19.    m = "[COPIA]";
  20.  
  21.    cout << "Despues de copia" << endl;
  22.  
  23.    return 0;
  24. }

Ver este ejemplo ejecutandose aqui: http://goo.gl/BdjA04
__________________
Visita mi perfil en LinkedIn

Última edición por CalgaryCorpus; 02/06/2014 a las 17:14
  #14 (permalink)  
Antiguo 10/06/2014, 17:09
Avatar de GumiCat  
Fecha de Ingreso: mayo-2014
Ubicación: Argentina
Mensajes: 16
Antigüedad: 10 años, 5 meses
Puntos: 0
Respuesta: Mi cadena se pierde

Cita:
Iniciado por vangodp Ver Mensaje
Calgary quizas nos quieras explicar mejor por que cres que no se esta llamando el destructor 2 veces para el mismo objeto si al final aparece 2 veces.
A ver que explicación pones tu en esto..

Código txt:
Ver original
  1. Constructor de: Hola
  2. Constructor de: Adios
  3. Destructor de Adios
  4. Destructor de ↑'=
  5.      
  6. << El programa ha finalizado: codigo de salida: 0 >>
  7. << Presione enter para cerrar esta ventana >>

Destructor de Adios
Destructor de ↑'=


si el destructor no sale 2 veces... a lo mejor soy yo que veo doble XD


Pues si has encontrado la solución pues ponla aquí para que mas personas la vean. mira que..
Eso que dice CalgaryCorpus, que la asignacion se hace miembro a miembro entre objetos. En este caso en uno temporal, entonces se comparte la misma direccion de memoria y luego al eliminarlo por primera vez con delete se limpia y la segunda ejecucion del destructor hace simbolitos raros por eso, porque ya se ha borrado con delete

Etiquetas: cadena, int, pierde, programa, string
Atención: Estás leyendo un tema que no tiene actividad desde hace más de 6 MESES, te recomendamos abrir un Nuevo tema en lugar de responder al actual.
Respuesta




La zona horaria es GMT -6. Ahora son las 17:34.