• Jueves 2 de Mayo de 2024, 19:24

Autor Tema:  El destructor me vuelve loco...  (Leído 4586 veces)

m0skit0

  • Miembro de PLATA
  • *****
  • Mensajes: 2337
  • Nacionalidad: ma
    • Ver Perfil
    • http://fr33kk0mpu73r.blogspot.com/
El destructor me vuelve loco...
« en: Viernes 17 de Octubre de 2008, 14:15 »
0
Hola chavales, ¿qué onda?

Estoy refrescando mi memoria en POO (y de paso aprendiendo la sintaxis de C++ de una vez  :P ) y he implementado una cola de enteros doblemente enlazada:

Código: C
  1.  
  2. struct tNodoCola
  3. {
  4.     int valor;
  5.     tNodoCola * sig;
  6.     tNodoCola * ant;
  7. };
  8.  
  9. struct tCabeceraCola
  10. {
  11.     tNodoCola *primero, *ultimo;
  12.     int numelementos;
  13. };
  14.  
  15. class cColaEnteros
  16. {
  17.     tCabeceraCola * pCabecera;
  18.    
  19. public:
  20.     //Constructor
  21.     cColaEnteros(void);
  22.  
  23.     //Destructor
  24.     ~cColaEnteros(void);
  25.  
  26.     //Operadores
  27.     cColaEnteros operator + (cColaEnteros cola);
  28.  
  29.     //Métodos
  30.         // Aquí van varios métodos...
  31.  
  32.     //Colegas
  33.     friend class cColaEnteros;
  34. };
  35.  
  36.  

El desctructor y el operador + implementados tal que así:

Código: C
  1.  
  2. cColaEnteros::~cColaEnteros(void)
  3. {
  4.     tNodoCola * aux1, * aux2;
  5.  
  6.     if (!this->Esta_Vacia())
  7.     {
  8.         aux1 = pCabecera->ultimo;
  9.  
  10.         while (aux1)
  11.         {
  12.             aux2 = aux1->ant;
  13.             delete aux1;
  14.             aux1 = aux2;
  15.         }
  16.  
  17.         delete pCabecera;
  18.     }
  19. }
  20.  
  21. cColaEnteros cColaEnteros::operator + (cColaEnteros cola)
  22. {
  23.     tNodoCola * aux;
  24.  
  25.     aux = cola.pCabecera->primero;
  26.  
  27.     while (aux)
  28.     {
  29.         this->Insertar_Elemento_Ultimo(aux->valor);
  30.         aux = aux->sig;
  31.     }  
  32.  
  33.     return *this;
  34. }
  35.  
  36.  

Sin embargo, me da error de violación de segmento :brickwall: en la línea (en main()):

Código: C
  1. cola3 = cola1 + cola2;
  2.  

Si imprimo los valores en el interior del operador, la cola this queda con los nuevos valores concatenados de cola, pero al salir del operador y querer imprimirlo en main(), veo que los valores de la cola son todos incorrectos, con punteros corruptos.

Si comento el destructor funciona bien, así que el problema es el destructor, ya que suprime los valores de ambas colas al salir del operador + (porque son variables locales al método). Pero necesito usar el destructor para liberar la memoria usada una vez finalizado el programa, y tampoco quiero que se tenga que llamar a un método de descarga cada vez que se deje de usar una cola, que para eso están los destructores. ¿Alguna idea de cual es el error?

¡Gracias de antemano!

EL_UNI

  • Nuevo Miembro
  • *
  • Mensajes: 19
  • Nacionalidad: es
    • Ver Perfil
Re: El destructor me vuelve loco...
« Respuesta #1 en: Viernes 17 de Octubre de 2008, 14:27 »
0
Has mirado que tengas bién hecho el crea??
Muchas veces (creo que a mi me pasaba siempre) es porque no se reserva bién la memoria a la hora de la creación. Puede que tu fallo esté ahí ^^

Revisalo también y nos cuentas :D
Programar es dejar fluir tu imaginación ^^ - EL_UNI

m0skit0

  • Miembro de PLATA
  • *****
  • Mensajes: 2337
  • Nacionalidad: ma
    • Ver Perfil
    • http://fr33kk0mpu73r.blogspot.com/
Re: El destructor me vuelve loco...
« Respuesta #2 en: Viernes 17 de Octubre de 2008, 14:36 »
0
Hmmm, pero las colas funcionan perfectamente si dejo sólo el destructor por defecto (el que no hace nada, vamos).

Aquí te dejo el constructor y los métodos de inserción de elementos que uso en main():

Código: C
  1.  
  2. cColaEnteros::cColaEnteros(void)
  3. {
  4.     pCabecera = new tCabeceraCola;
  5.     pCabecera->primero = NULL;
  6.     pCabecera->ultimo = NULL;
  7.     pCabecera->numelementos = 0;
  8. }
  9.  
  10. // Inserta un elemento al principio de la cola
  11. void cColaEnteros::Insertar_Elemento_Primero(int elemento)
  12. {
  13.     tNodoCola * aux;
  14.  
  15.     //Creamos el nuevo elemento
  16.     aux = new tNodoCola;
  17.     aux->valor = elemento;
  18.     aux->ant = NULL;
  19.  
  20.     //Si la cola no tiene ningún elemento
  21.     if(this->Esta_Vacia())
  22.     {
  23.         aux->sig = NULL;
  24.         pCabecera->primero = aux;
  25.         pCabecera->ultimo = aux;
  26.     }
  27.     //Si ya hay alguno
  28.     else
  29.     {
  30.         pCabecera->primero->ant = aux;
  31.         aux->sig = pCabecera->primero;
  32.         pCabecera->primero = aux;
  33.     }
  34.  
  35.     pCabecera->numelementos++;
  36. }
  37.  
  38. // Inserta un elemento al final de la cola
  39. void cColaEnteros::Insertar_Elemento_Ultimo(int elemento)
  40. {
  41.     tNodoCola * aux;
  42.    
  43.     //Creamos el nuevo elemento
  44.     aux = new tNodoCola;
  45.     aux->valor = elemento;
  46.     aux->sig = NULL;    
  47.    
  48.     //Si la cola no tiene ningún elemento
  49.     if(this->Esta_Vacia())
  50.     {
  51.         aux->ant = NULL;
  52.         pCabecera->primero = aux;
  53.         pCabecera->ultimo = aux;
  54.     }
  55.     //Si ya hay alguno
  56.     else
  57.     {
  58.         pCabecera->ultimo->sig = aux;
  59.         aux->ant = pCabecera->ultimo;
  60.         pCabecera->ultimo = aux;
  61.     }
  62.  
  63.     pCabecera->numelementos++;
  64. }
  65.  
  66.  

Y ya que estamos, main():

Código: C
  1.  
  2. int main(void)
  3. {
  4.     cColaEnteros cola1, cola2, cola3;
  5.     int i;
  6.    
  7.     for (i=0;i<=15;i++)
  8.     {
  9.         cola1.Insertar_Elemento_Ultimo(i);
  10.         cola2.Insertar_Elemento_Primero(i+10);
  11.     }
  12.    
  13.     cola3 = cola1 + cola2;
  14.  
  15.     cola3.Imprimir_Elementos();
  16.  
  17.     return 0;
  18. }
  19.  
  20.  

EL_UNI

  • Nuevo Miembro
  • *
  • Mensajes: 19
  • Nacionalidad: es
    • Ver Perfil
Re: El destructor me vuelve loco...
« Respuesta #3 en: Viernes 17 de Octubre de 2008, 14:52 »
0
Le he dado unas cuantas vueltas, pero no consigo ver el error... es más, me parece que esta todo bien...
Puedes pasar el codigo completo (si hay algo que no quieras poner no lo hagas... es solo para probar a compilarlo y depurarlo)
Programar es dejar fluir tu imaginación ^^ - EL_UNI

m0skit0

  • Miembro de PLATA
  • *****
  • Mensajes: 2337
  • Nacionalidad: ma
    • Ver Perfil
    • http://fr33kk0mpu73r.blogspot.com/
Re: El destructor me vuelve loco...
« Respuesta #4 en: Viernes 17 de Octubre de 2008, 15:09 »
0
Sí , claro, no hay problema en pasarte el código completo, sólo estoy frikeando con él  :P

P.D: Uso VC++. Las tripas del destructor están comentadas.
El mensaje contiene 1 archivo adjunto. Debes ingresar o registrarte para poder verlo y descargarlo.

Eternal Idol

  • Moderador
  • ******
  • Mensajes: 4696
  • Nacionalidad: ar
    • Ver Perfil
Re: El destructor me vuelve loco...
« Respuesta #5 en: Viernes 17 de Octubre de 2008, 15:18 »
0
El problema son las copias generadas por usar parametros por valor, asi te funcionaria:

cColaEnteros & operator + (cColaEnteros &cola);

Nacional y Popular En mi país la bandera de Eva es inmortal.


Queremos una Argentina socialmente justa, económicamente libre y  políticamente soberana.
¡Perón cumple, Evita dignifica!


La mano invisible del mercado me robo la billetera.

EL_UNI

  • Nuevo Miembro
  • *
  • Mensajes: 19
  • Nacionalidad: es
    • Ver Perfil
Re: El destructor me vuelve loco...
« Respuesta #6 en: Viernes 17 de Octubre de 2008, 15:20 »
0
A mi no me ha dado error ninguno :S Solo me decia que lo de hacerse amigo a si mismo estaba implicito... que no hace falta ponerlo. Por lo demas todo bien. Por cierto deja una linea en blanco al final del fichero. Da errores raros luego.

Solo decirte que yo uso el eclipse con MinGW.
Programar es dejar fluir tu imaginación ^^ - EL_UNI

m0skit0

  • Miembro de PLATA
  • *****
  • Mensajes: 2337
  • Nacionalidad: ma
    • Ver Perfil
    • http://fr33kk0mpu73r.blogspot.com/
Re: El destructor me vuelve loco...
« Respuesta #7 en: Viernes 17 de Octubre de 2008, 21:18 »
0
Cita de: "EL_UNI"
A mi no me ha dado error ninguno

¿Descomentaste el destructor?

Cita de: "Eternal Idol"
por usar parametros por valor

Precisamente, si los paso por valor, ¿por qué los devuelve modificados?  :P

Eternal Idol

  • Moderador
  • ******
  • Mensajes: 4696
  • Nacionalidad: ar
    • Ver Perfil
Re: El destructor me vuelve loco...
« Respuesta #8 en: Viernes 17 de Octubre de 2008, 22:10 »
0
Cita de: "m0skit0"
Precisamente, si los paso por valor, ¿por qué los devuelve modificados?  :P

cola3 = cola1 + cola2;

es lo mismo que:
cola3.operator=(cola1.operator+(cola2));

al no estar el operador = sobrecargado nos podemos quedar con:
cola3  = cola1.operator+(cola2);

entonces vamos al operador + que termina asi:
return *this;

por lo tanto esto se reduce a (despues de la suma):
cola3 = cola1;

PERO cola1 (ahora es en realidad la variable cola del operador) es una copia TEMPORAL que desaparece al terminar el operador, por eso si no ejecutas el destructor no se destruye la memoria.

Si pones un cout << "destructor" endl; en el destructor vas a ver que se lo llama 5 veces, 2 por la copia y tres por las variables del main. Despues de llamarse al destructor por las copias lo que asigne a cola3 ya no es valido  :clown:

Nacional y Popular En mi país la bandera de Eva es inmortal.


Queremos una Argentina socialmente justa, económicamente libre y  políticamente soberana.
¡Perón cumple, Evita dignifica!


La mano invisible del mercado me robo la billetera.

m0skit0

  • Miembro de PLATA
  • *****
  • Mensajes: 2337
  • Nacionalidad: ma
    • Ver Perfil
    • http://fr33kk0mpu73r.blogspot.com/
Re: El destructor me vuelve loco...
« Respuesta #9 en: Viernes 17 de Octubre de 2008, 22:44 »
0
Excelente explicación  :beer:

Pero la cuestión es cómo lo haría para sumar sin usar punteros  &lt;_&lt;

Eternal Idol

  • Moderador
  • ******
  • Mensajes: 4696
  • Nacionalidad: ar
    • Ver Perfil
Re: El destructor me vuelve loco...
« Respuesta #10 en: Viernes 17 de Octubre de 2008, 22:46 »
0
Como te decia antes simplemente cambiando la signature del operador solucionas el problema:

cColaEnteros &operator + (cColaEnteros &cola);

cColaEnteros &operator + (cColaEnteros &cola)
{
//tu codigo actual
}

Nacional y Popular En mi país la bandera de Eva es inmortal.


Queremos una Argentina socialmente justa, económicamente libre y  políticamente soberana.
¡Perón cumple, Evita dignifica!


La mano invisible del mercado me robo la billetera.

EL_UNI

  • Nuevo Miembro
  • *
  • Mensajes: 19
  • Nacionalidad: es
    • Ver Perfil
Re: El destructor me vuelve loco...
« Respuesta #11 en: Sábado 18 de Octubre de 2008, 00:10 »
0
He implementado esta noche una cola doble de enteros...
Todo funciona bién, pero tengo un problema con el operator +. Y es que no hace nada... bueno cuando lo depuras me dice que no puede acceder a una dirección de memoria... he amoldado la funcion para mi codigo pero nada...
Si pudierais explicarme que como funciona exactamente esa función os lo agradecería.
Programar es dejar fluir tu imaginación ^^ - EL_UNI

m0skit0

  • Miembro de PLATA
  • *****
  • Mensajes: 2337
  • Nacionalidad: ma
    • Ver Perfil
    • http://fr33kk0mpu73r.blogspot.com/
Re: El destructor me vuelve loco...
« Respuesta #12 en: Sábado 18 de Octubre de 2008, 00:35 »
0
Código: C
  1.  
  2. cColaEnteros & operator + (cColaEnteros &cola);
  3.  
  4. cColaEnteros & cColaEnteros::operator + (cColaEnteros &cola)
  5. {
  6.     //la operación es *this + cola
  7.     tNodoCola * aux;
  8.     //aux nos va a servir para recorrer cola
  9.     aux = cola.pCabecera->primero;
  10.     //mientras aux no sea NULL (no haya siguiente)
  11.     while (aux)
  12.     {
  13.         //insertamos el elemento de cola al final de *this
  14.         this->Insertar_Elemento_Ultimo(aux->valor);
  15.         //pasamos al siguiente elemento
  16.         aux = aux->sig;
  17.     }  
  18.     //devolvemos el resultado
  19.     return *this;
  20. }
  21.  
  22.  

No hay ningún cambio al ponerlo así, Eternal Idol.

Aquí la tienes comentada, EL_UNI

Eternal Idol

  • Moderador
  • ******
  • Mensajes: 4696
  • Nacionalidad: ar
    • Ver Perfil
Re: El destructor me vuelve loco...
« Respuesta #13 en: Sábado 18 de Octubre de 2008, 00:44 »
0
¿Recompilaste?
¿No es este el output que queres acaso?:
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10

Sin ese cambio se obtenia un loop infinito con numeros sin sentido ...

Acabo de volver a bajar tu codigo:

1. Compilo y ejecuto, sale el output de arriba.
2. Descomento el destructor, salen numeros hasta que me canso y le doy a ctrl+c.
3. Agrego las referencias mencionadas, sale el output de arriba.

Todo esto simplemente haciendo cl archivo.cpp (o mejor cl archivo.cpp /EHsc /Zi). VC++ 8 (Visual Studio 2005).

Nacional y Popular En mi país la bandera de Eva es inmortal.


Queremos una Argentina socialmente justa, económicamente libre y  políticamente soberana.
¡Perón cumple, Evita dignifica!


La mano invisible del mercado me robo la billetera.

m0skit0

  • Miembro de PLATA
  • *****
  • Mensajes: 2337
  • Nacionalidad: ma
    • Ver Perfil
    • http://fr33kk0mpu73r.blogspot.com/
Re: El destructor me vuelve loco...
« Respuesta #14 en: Sábado 18 de Octubre de 2008, 00:57 »
0
Cita de: "Eternal Idol"
1. Compilo y ejecuto, sale el output de arriba.
2. Descomento el destructor, salen numeros hasta que me canso y le doy a ctrl+c.
3. Agrego las referencias mencionadas, sale el output de arriba.

Pues a mí no me funciona así... Yo también me lo he tenido que bajar de aquí mismo porque lo hice en otro PC.

Con el destructor, no funciona ni como lo puse yo ni con el operador de dirección (&) que has comentado.

Aquí está el error:

[attachment=0:1ff37riq]captura18-10-08.JPG[/attachment:1ff37riq]

Debido a que las referencias a memoria están mal y por tanto el acceso a la memoria aux->valor no está permitido.

EDIT: Ahora que lo pienso, es posible que a ti te salgan los números raros porque te accede a una memoria accesible por tu proceso, y en el mío no, ya que los valores que pueden tomar las referencias erróneas diferirán en cada PC.
El mensaje contiene 1 archivo adjunto. Debes ingresar o registrarte para poder verlo y descargarlo.
« última modificación: Sábado 18 de Octubre de 2008, 01:05 por m0skit0 »

Eternal Idol

  • Moderador
  • ******
  • Mensajes: 4696
  • Nacionalidad: ar
    • Ver Perfil
Re: El destructor me vuelve loco...
« Respuesta #15 en: Sábado 18 de Octubre de 2008, 01:02 »
0
Subi el codigo, el ejecutable y el pdb ... sino compilalo desde linea de comandos y fijate que pasa ...

Citar
EDIT: Ahora que lo pienso, es posible que a ti te salgan los números raros porque te accede a una memoria accesible por tu proceso, y en el mío no, ya que los valores que pueden tomar las referencias erróneas diferirán en cada PC.

Si, muy bien, pero eso solo pasa cuando se usa el operador + con los parametros por valor y el destructor liberando la memoria. Fijate CUANDO se llama al destructor depurando ...

Nacional y Popular En mi país la bandera de Eva es inmortal.


Queremos una Argentina socialmente justa, económicamente libre y  políticamente soberana.
¡Perón cumple, Evita dignifica!


La mano invisible del mercado me robo la billetera.

m0skit0

  • Miembro de PLATA
  • *****
  • Mensajes: 2337
  • Nacionalidad: ma
    • Ver Perfil
    • http://fr33kk0mpu73r.blogspot.com/
Re: El destructor me vuelve loco...
« Respuesta #16 en: Sábado 18 de Octubre de 2008, 01:19 »
0
Sí, tienes razón, sí que funciona mejor con el & (no sé cómo demonios lo puse antes  :huh:), pero da otro error de puntero corrupto al ejecutar el destructor de cola3 (sé que es cola3 porque primero pasa por cola1 y cola2):
[attachment=0:29zbsbz5]captura2.JPG[/attachment:29zbsbz5]
El mensaje contiene 1 archivo adjunto. Debes ingresar o registrarte para poder verlo y descargarlo.

Eternal Idol

  • Moderador
  • ******
  • Mensajes: 4696
  • Nacionalidad: ar
    • Ver Perfil
Re: El destructor me vuelve loco...
« Respuesta #17 en: Sábado 18 de Octubre de 2008, 01:24 »
0
Cita de: "m0skit0"
Sí, tienes razón, sí que funciona mejor con el & (no sé cómo demonios lo puse antes  :huh:), pero da otro error de puntero corrupto al ejecutar el destructor de cola3 (sé que es cola3 porque primero pasa por cola1 y cola2):

¿Miraste el codigo generado? En el mio al menos se destruyen en orden inverso (cola3, cola2, cola1) y sin problemas ...

Nacional y Popular En mi país la bandera de Eva es inmortal.


Queremos una Argentina socialmente justa, económicamente libre y  políticamente soberana.
¡Perón cumple, Evita dignifica!


La mano invisible del mercado me robo la billetera.

m0skit0

  • Miembro de PLATA
  • *****
  • Mensajes: 2337
  • Nacionalidad: ma
    • Ver Perfil
    • http://fr33kk0mpu73r.blogspot.com/
Re: El destructor me vuelve loco...
« Respuesta #18 en: Sábado 18 de Octubre de 2008, 01:32 »
0
Creo que sé lo que pasa.

Haciendo una inspección, me doy cuenta de que cola1 y cola3 hacen referencia a la misma memoria, por tanto al destruirse cola3 se destruye también cola1, pero luego se vuelve a llamar al destructor de cola1, con el consiguiente desastre. El problema supongo que vendrá del operador = que no está definido para esta clase. Voy a crearlo y te sigo comentando.

Por cierto, ¡gracias Eternal Idol!

EDIT: en realidad habría que cambiar el operador + también. Me estoy dando cuenta de lo mal hecho que está...  :lol:

m0skit0

  • Miembro de PLATA
  • *****
  • Mensajes: 2337
  • Nacionalidad: ma
    • Ver Perfil
    • http://fr33kk0mpu73r.blogspot.com/
Re: El destructor me vuelve loco...
« Respuesta #19 en: Sábado 18 de Octubre de 2008, 01:49 »
0
¡Ahora sí que va!

Código: C
  1.  
  2. cColaEnteros &cColaEnteros::operator + (cColaEnteros &cola)
  3. {
  4.     cColaEnteros * aux;
  5.     tNodoCola * paux;
  6.  
  7.     aux = new cColaEnteros;
  8.  
  9.     paux = this->pCabecera->primero;
  10.     while (paux)
  11.     {
  12.         aux->Insertar_Elemento_Ultimo(paux->valor);
  13.         paux = paux->sig;
  14.     }
  15.  
  16.     paux = cola.pCabecera->primero;
  17.  
  18.     while (paux)
  19.     {
  20.         aux->Insertar_Elemento_Ultimo(paux->valor);
  21.         paux = paux->sig;
  22.     }
  23.  
  24.     return *aux;
  25. }
  26.  
  27.  

Gracias de nuevo, Eternal Idol

Eternal Idol

  • Moderador
  • ******
  • Mensajes: 4696
  • Nacionalidad: ar
    • Ver Perfil
Re: El destructor me vuelve loco...
« Respuesta #20 en: Sábado 18 de Octubre de 2008, 03:42 »
0
Mierda, funciona pero tiene un memory leak de esta manera, nadie llama a delete por este new: aux = new cColaEnteros;.

Todos los ejemplos que encuentro devuelven por VALOR (usando un objeto temporal!  :argh:  :argh:  :argh: ) y ninguno parece funcionar en este caso ya que como vimos el destructor es llamado al terminar el operador y los valores son basura desde ese momento en adelante.

Si usaras punteros no habria problema  :adios:

Un hack para que funcione usando como decias el operador =:
Código: Text
  1. bool cColaEnteros::Esta_Vacia(void)
  2. {
  3.     return pCabecera ? !pCabecera->numelementos : true;
  4. }
  5.  
  6. cColaEnteros& operator= (/*const*/ cColaEnteros& param)
  7. {
  8.     pCabecera = param.pCabecera;
  9.     param.pCabecera = 0;
  10.     delete &param;
  11.     return *this;
  12. }
  13.  

O tambien en combinacion con el operador = usar un constructor especial con un parametro tipo allocatedMemory a true en el operador + y comprobar eso en el destructor antes de llamar a Esta_Vacia, creo que la STL hace algo parecido a esto.

Igual no me cierra el tema todavia ...

Nacional y Popular En mi país la bandera de Eva es inmortal.


Queremos una Argentina socialmente justa, económicamente libre y  políticamente soberana.
¡Perón cumple, Evita dignifica!


La mano invisible del mercado me robo la billetera.

m0skit0

  • Miembro de PLATA
  • *****
  • Mensajes: 2337
  • Nacionalidad: ma
    • Ver Perfil
    • http://fr33kk0mpu73r.blogspot.com/
Re: El destructor me vuelve loco...
« Respuesta #21 en: Sábado 18 de Octubre de 2008, 07:01 »
0
Cita de: "Eternal Idol"
nadie llama a delete por este new: aux = new cColaEnteros;

¿Cómo no? Ese objeto se asigna a la vuelta de la función (en este caso a cola3) y se llama a su destructor. ¿O me estoy equivocando?

Cita de: "Eternal Idol"
Si usaras punteros no habria problema


Lo sé, el reto es hacerlo sin  :hitcomp: jeje.

EDIT: efectivamente, la depuración dice que sí se destruye. Es la misma dirección de memoria (del pCabecera) la que se la asigna a aux en el operador que a la hora de destruir cola3. ¡Por fin!

Eternal Idol

  • Moderador
  • ******
  • Mensajes: 4696
  • Nacionalidad: ar
    • Ver Perfil
Re: El destructor me vuelve loco...
« Respuesta #22 en: Sábado 18 de Octubre de 2008, 10:16 »
0
Cita de: "m0skit0"
¿Cómo no? Ese objeto se asigna a la vuelta de la función (en este caso a cola3) y se llama a su destructor. ¿O me estoy equivocando?

Eso (casi, el delete obviamente es manual) pasaria si cola3 fuera un puntero, como NO lo es, simplemente se asigna un puntero (pCabecera) pero cola3 siempre apunta a la misma direccion de memoria en la pila.

Cita de: "m0skit0"
EDIT: efectivamente, la depuración dice que sí se destruye. Es la misma dirección de memoria (del pCabecera) la que se la asigna a aux en el operador que a la hora de destruir cola3. ¡Por fin!

Nopes, ciertamente cola3.pCabecera es la misma direccion que paux = this->pCabecera pero cola3 (&cola3 si queres) no es la misma que aux = new cColaEnteros;. Para comprobarlo experimentalmente lo que hice fue sobrecargar new y delete en la clase ... se llama a un new y nunca a delete. Tene en cuenta que el destructor de cColaEnteros se llama por cola1, cola2 y cola3, jamas para el objeto creado dinamicamente (otra cosa es que este objeto, cola3, comparta campos - punteros - que son liberados con el objeto creado dinamicamente, pero no es suficiente para liberar el objeto en si mismo). Una forma de solucionarlo simple pasa por liberar ese objeto en el operador de asignacion, por ejemplo de esta otra manera:

Código: Text
  1. cColaEnteros &cColaEnteros::operator + (cColaEnteros &cola)
  2. {
  3.     cColaEnteros * aux;
  4.     tNodoCola * paux;
  5.  
  6.     aux = new cColaEnteros(false); //la unica diferencia es que pasamos false al constructor
  7.     //sigue como siempre
  8. }
  9.  
  10. cColaEnteros::cColaEnteros(bool fMemory = true)
  11. {
  12.     pCabecera = new tCabeceraCola;
  13.     pCabecera->primero = NULL;
  14.     pCabecera->ultimo = NULL;
  15.     pCabecera->numelementos = 0;
  16.     freeMemory = fMemory; //miembro privado freeMemory, indica si liberamos o no la memoria DENTRO el objeto
  17. }
  18.  
  19. cColaEnteros::~cColaEnteros(void)
  20. {                              
  21.     tNodoCola * aux1, * aux2;
  22.  
  23.     if (!freeMemory) { return; } //si fue creado por el operador + solo liberamos el objeto de la clase cColaEnteros, en sintesis los 4 bytes del puntero a pCabecera, y retornamos sin tocar lo de adentro
  24.     //sigue como siempre
  25. }
  26.  
  27. cColaEnteros& operator= (/*const*/ cColaEnteros& param)
  28. {
  29.   pCabecera = param.pCabecera; //lo unico que hace el operador de asignacion normalmente
  30.   delete &param; //ahora si, liberamos lo reservado en aux = new cColaEnteros;
  31.   return *this; //lo unico que hace el operador de asignacion normalmente
  32. }
  33.  
  34. En cColaEnteros agregamos un miembro privado de tipo bool llamado freeMemory.
  35.  

Puede que me confunda pero creo que al final lo que hace la STL es algo asi, devolviendo por valor y marcando la no destruccion interna (nos olvidamos de new, delete y el operador =):
Código: Text
  1. cColaEnteros cColaEnteros::operator + (cColaEnteros &cola)
  2. {
  3.     cColaEnteros aux(false); //objeto temporal señalado para no destruir  internamente en el destructor ... el objeto en si mismo es destruido despues de la asignacion, estas dos afirmaciones son clave para garantizar que pCabecera es valido. No puede sobreescribirse el puntero pCabecera ya que la asignacion es anterior a su destruccion y no tocamos los campos internos por lo que al usarlos desde el operando de la asignacion seran validos.
  4.  
  5.     paux = this->pCabecera->primero;
  6.     while (paux)
  7.     {
  8.         aux.Insertar_Elemento_Ultimo(paux->valor);
  9.         paux = paux->sig;
  10.     }
  11.  
  12.     paux = cola.pCabecera->primero;
  13.  
  14.     while (paux)
  15.     {
  16.         aux.Insertar_Elemento_Ultimo(paux->valor);
  17.         paux = paux->sig;
  18.     }
  19.     return aux;
  20. }
  21.  
  22. cColaEnteros::~cColaEnteros(void) //es lo mismo que la solucion anterior
  23. {                              
  24.     tNodoCola * aux1, * aux2;
  25.  
  26.     if (!freeMemory) { return; } //si fue creado por el operador + solo liberamos el objeto de la clase cColaEnteros, en sintesis los 4 bytes del puntero a pCabecera, y retornamos sin tocar lo de adentro
  27.     //sigue como siempre
  28. }
  29.  
  30. cColaEnteros::cColaEnteros(bool fMemory = true) //es lo mismo que la solucion anterior
  31. {
  32.     pCabecera = new tCabeceraCola;
  33.     pCabecera->primero = NULL;
  34.     pCabecera->ultimo = NULL;
  35.     pCabecera->numelementos = 0;
  36.     freeMemory = fMemory; //miembro privado freeMemory, indica si liberamos o no la memoria DENTRO el objeto
  37. }
  38.  

Nacional y Popular En mi país la bandera de Eva es inmortal.


Queremos una Argentina socialmente justa, económicamente libre y  políticamente soberana.
¡Perón cumple, Evita dignifica!


La mano invisible del mercado me robo la billetera.

EL_UNI

  • Nuevo Miembro
  • *
  • Mensajes: 19
  • Nacionalidad: es
    • Ver Perfil
Re: El destructor me vuelve loco...
« Respuesta #23 en: Sábado 18 de Octubre de 2008, 11:59 »
0
Está saliendo un código un poco lioso, no es más fácil implementarle una función a la clase para que concatene dos colas pasadas como parametros?

Siento no haber podido responder antes... pero como soy usuario nuevo no puedo enviar mas de X mensajes por día... :S

Y otra cosa m0skit0... porque no usas punteros a colas?? Lo único que tienes que tener cuidado es de acordarte de crearlos y destruirlos. A demás, dan mucho más juego... aunque también más errores por culpa de esto xDD

Una pregunta... porque no usais varios archivos... lo introducis todo en un mismo .cpp. Es mucho mejor y más cómodo luego revisar código si los separas en cabeceras (.h) y código (.cpp). En mi caso tengo colaIntDoble.h, colaIntDoble.cpp y main.cpp. Es solo por comentar... no reprocho nada xDDD
Programar es dejar fluir tu imaginación ^^ - EL_UNI

Eternal Idol

  • Moderador
  • ******
  • Mensajes: 4696
  • Nacionalidad: ar
    • Ver Perfil
Re: El destructor me vuelve loco...
« Respuesta #24 en: Sábado 18 de Octubre de 2008, 12:33 »
0
Cita de: "EL_UNI"
Está saliendo un código un poco lioso, no es más fácil implementarle una función a la clase para que concatene dos colas pasadas como parametros?

Puede ser pero tal vez la gracia es usar sobrecarga de operadores ...

Cita de: "EL_UNI"
Una pregunta... porque no usais varios archivos... lo introducis todo en un mismo .cpp. Es mucho mejor y más cómodo luego revisar código si los separas en cabeceras (.h) y código (.cpp). En mi caso tengo colaIntDoble.h, colaIntDoble.cpp y main.cpp. Es solo por comentar... no reprocho nada xDDD

Ciertamente es preferible modularizar el codigo pero para resolver este problema es irrelevante (y cuantos menos archivos haya que subir/bajar de la red mejor).

Nacional y Popular En mi país la bandera de Eva es inmortal.


Queremos una Argentina socialmente justa, económicamente libre y  políticamente soberana.
¡Perón cumple, Evita dignifica!


La mano invisible del mercado me robo la billetera.