Duda con punteros

Iniciado por SrMcLister, 1 Junio 2018, 19:15 PM

0 Miembros y 2 Visitantes están viendo este tema.

SrMcLister

Buenas a tod@s!!
Tengo una pregunta ya que he estado cursando hasta hace poco la asignatura de Programación y Estructura de datos, y en las prácticas hemos trabajado con memoria dinámica.
Mi pregunta es la siguiente...
En el tipo Lista de datos creado, tengo una clase Nodo que contiene un numero(int), normal y corriente, y un puntero a otro nodo llamado siguiente.

Código (cpp) [Seleccionar]


class Nodo{
  friend class Lista;
private:
  int n;
  Nodo* siguiente;
...
}



Y una lista que contiene un puntero a Nodo que apunta a la cabeza.

Código (cpp) [Seleccionar]


class Lista{
  friend class Nodo;
private:
  Nodo *primero;
...
}



Mi pregunta se genera al tratar de insertar en dicha lista ya que en el método insertar, lo que hago es crear un nodo mediante new, tal que...

Código (cpp) [Seleccionar]


bool Lista::Insertar(const int &n){
  Nodo *nodoaux = new Nodo;
  nodoaux->n = n;
  this->primero=nodoaux;
  return true;
}



Pero gracias a Valgrind, me he dado cuenta que todo esa memoria dinamica que estoy creando no la puedo borrar, ya que si hago el delete nodoaux; nodoaux=NULL; antes de el return, me aparece basura al salir del metodo y regresar al programa principal.
Entiendo que es porque estoy borrando un puntero que he creado con los datos.
¿Habría alguna forma de salir del método, aun creando dentro de el un puntero a Nodo, igualando el principio de mi lista a ese puntero y gestionar bien la memoria?

(Solo pongo el código para insertar al principio de la lista, los demás casos los he contemplado en mi práctica también pero con una gestión de memoria malisima  :xD )

Espero respuesta!
Muchas gracias  :rolleyes: :rolleyes:
Código (cpp) [Seleccionar]

return((u.areHappy() && u.knowIt()) ? u.clapYourHands() : u.goFuckYourself());

ThunderCls

#1
Si haces lo siguiente:

Código (cpp) [Seleccionar]

Nodo *nodoaux = new Nodo;
nodoaux->n = n;
this->primero=nodoaux;
delete nodoaux;


Es lo mismo que si hicieras algo como esto:
Código (cpp) [Seleccionar]

Nodo *nodoaux = new Nodo;
nodoaux->n = n;
this->primero=nodoaux;
delete this->primero;


No hay diferencias. Primero tienes que entender bien el concepto de punteros. En esta linea:
Código (cpp) [Seleccionar]
this->primero=nodoaux;

Solo estas copiando una direccion de memoria donde esta alojado un objeto "Nodo" y NO el objeto "Nodo" en si. Lo que seria lo mismo:

Código (cpp) [Seleccionar]
nodoaux=0x00001->Nodo
this->primero=0x00001->Nodo


Por lo que si destruyes el objeto Nodo, dicha direccion de memoria (puntero) estara apuntando a basura en ambas variables, ya que ambas contenian la misma direccion de memoria (apuntaban al mismo objeto). En este caso debes implemetar la liberacion de memoria directamente en tu Lista ya sea en el destructor y/o en algun otro metodo destinado a ello (Clear, Free, etc).

Código (cpp) [Seleccionar]
while ((actual = primero) != NULL) {
    primero = primero->siguiente;         
    delete actual;
    actual = null;
}
-[ "...I can only show you the door. You're the one that has to walk through it." – Morpheus (The Matrix) ]-
http://reversec0de.wordpress.com
https://github.com/ThunderCls/

SrMcLister

Buenas ThunderCls.

Si, entiendo que el Nodo que creo que es el que le meto el numero y apunta a primero es la misma dirección de memoria.
Y si, en el tema de punteros he incidido bastante.
El tema del destructor también lo controlo y está bien hecho.
Sigo investigando, cuando tenga la solución la pongo por aquí.
Un Saludo y gracias por tu respuesta!
Código (cpp) [Seleccionar]

return((u.areHappy() && u.knowIt()) ? u.clapYourHands() : u.goFuckYourself());

MAFUS

Entiendo que más que una lista es una pila, cada vez que insertas algo lo haces en la cabeza y lo que era la lista original pasa a la cola.

SrMcLister

Cita de: MAFUS en  7 Junio 2018, 14:06 PM
Entiendo que más que una lista es una pila, cada vez que insertas algo lo haces en la cabeza y lo que era la lista original pasa a la cola.

Es una lista, lo que pasa es que para resumir mi caso he puesto el insertar en cabeza de la lista, tengo el caso de insertar al final de la lista e insertar en medio, pero si es una lista, la pila no la he implementado...
Lo único es que en vez de estar implementada secuencialmente, está enlazada mediante punteros.
Un Saludo.
Código (cpp) [Seleccionar]

return((u.areHappy() && u.knowIt()) ? u.clapYourHands() : u.goFuckYourself());

ThunderCls

Cita de: SrMcLister en  7 Junio 2018, 13:58 PM
Buenas ThunderCls.

Si, entiendo que el Nodo que creo que es el que le meto el numero y apunta a primero es la misma dirección de memoria.
Y si, en el tema de punteros he incidido bastante.
El tema del destructor también lo controlo y está bien hecho.
Sigo investigando, cuando tenga la solución la pongo por aquí.
Un Saludo y gracias por tu respuesta!

Hola

Pues si dominas todos estos aspectos que te comento entonces no entiendo donde tienes el problema. Tu pregunta inicial era "como gestionar bien la memoria en una lista simplemente enlazada"...bueno, pues creo que ya tienes la respuesta. Es sencillo, resumiendo, no puedes usar codigo de liberacion de memoria en el mismo metodo "Insertar", a no ser que uses copia de objecto en vez de copia de puntero. Necesitas crearte una funcion en la clase Lista que se encargue de liberar la memoria dinamica una vez hayas terminado de usarla. Al final de mi post anterior te puse un pseudocodigo como ejemplo.
Saludos
-[ "...I can only show you the door. You're the one that has to walk through it." – Morpheus (The Matrix) ]-
http://reversec0de.wordpress.com
https://github.com/ThunderCls/

MAFUS

No domino C++ así que no puedo mostrarte cómo se hace con su sintaxis, pero si con C, por si te sirve de ayuda.

SrMcLister

Cita de: MAFUS en  7 Junio 2018, 16:44 PM
No domino C++ así que no puedo mostrarte cómo se hace con su sintaxis, pero si con C, por si te sirve de ayuda.
Te entiendo, muchas gracias pero la práctica es en C++.
Estoy buscando la solución. La pondré cuando la tenga.
Un Saludo.
Código (cpp) [Seleccionar]

return((u.areHappy() && u.knowIt()) ? u.clapYourHands() : u.goFuckYourself());

SrMcLister

Cita de: ThunderCls en  7 Junio 2018, 15:50 PM
Hola

Pues si dominas todos estos aspectos que te comento entonces no entiendo donde tienes el problema. Tu pregunta inicial era "como gestionar bien la memoria en una lista simplemente enlazada"...bueno, pues creo que ya tienes la respuesta. Es sencillo, resumiendo, no puedes usar codigo de liberacion de memoria en el mismo metodo "Insertar", a no ser que uses copia de objecto en vez de copia de puntero. Necesitas crearte una funcion en la clase Lista que se encargue de liberar la memoria dinamica una vez hayas terminado de usarla. Al final de mi post anterior te puse un pseudocodigo como ejemplo.
Saludos

Buenas, gracias por responder, estoy intentando guardar el contenido de ese nodo en algún puntero no dinamico, para igualarlo a primero, si lo consigo lo comento.
Un Saludo.
Código (cpp) [Seleccionar]

return((u.areHappy() && u.knowIt()) ? u.clapYourHands() : u.goFuckYourself());