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

[SOLUCIONADO] Duda con punteros

Estas en el tema de Duda con punteros en el foro de C/C++ en Foros del Web. Hola amigos! Tengo una duda y es que si quiero asignar memoria a un puntero debo liberar la memoria que ya tiene almacenada de manera ...
  #1 (permalink)  
Antiguo 16/07/2016, 01:34
Avatar de Andrek  
Fecha de Ingreso: enero-2012
Mensajes: 14
Antigüedad: 12 años, 2 meses
Puntos: 1
Duda con punteros

Hola amigos!

Tengo una duda y es que si quiero asignar memoria a un puntero debo liberar la memoria que ya tiene almacenada de manera dinamica?

Ejemplo:

Código:
class X
{
public:
    int n;
};

int main(int argc, char* args[])
{
    X *p;
    p = new X;
    delete p; // Es necesario?
    p = new X;
    delete p;
    return 0;
}
Intente quitando el primer 'delete p' y no se como ver si el resultado es que tengo ahora 2 clases X.

Gracias por leer!
  #2 (permalink)  
Antiguo 16/07/2016, 04:40
Avatar de xKuZz  
Fecha de Ingreso: febrero-2015
Ubicación: nullptr
Mensajes: 183
Antigüedad: 9 años, 1 mes
Puntos: 27
Respuesta: Duda con punteros

Un puntero apunta a una única dirección de memoria, en tu caso con el primer new has reservado espacio para una clase X y la has creado con el constructor por defecto, has liberado ese espacio, nas vuelto a reservar y crear la clase X con el constructor por defecto y has vuelto a liberar ese espacio. El delete es necesario para que no se produzca una fuga de memoria en ese caso.

Para conseguir lo que tu quieres has de utilizar la variación de new/ delete con []

Código C++:
Ver original
  1. int main(int argc, char* args[])
  2. {
  3.     X *p;
  4.     p = new X[2]; // Cogemos y creamos dos clases X memorias en contigua
  5.     p[0].n = 3;   // p[0] == *p es la primera clase X
  6.     p[1].n = 4;   // p[1] == *(p + 1) es la segunda clase X que hemos creado
  7.     delete[] p;   // Para realizar delete utilizamos la variación con []
  8.     return 0;
  9. }
  #3 (permalink)  
Antiguo 16/07/2016, 06:45
Avatar de Andrek  
Fecha de Ingreso: enero-2012
Mensajes: 14
Antigüedad: 12 años, 2 meses
Puntos: 1
Respuesta: Duda con punteros

Gracias por contestar amigo!

Pero eso no resuelve mi duda, yo necesito crear clases aleatorias cada cierto tiempo, por eso estoy preguntando si al usar el operador 'new' el vacia automaticamente el puntero o solo devuelve una direccion y mi puntero solo cambia de direccion y no libera la memoria que esta usando.

Ejemplo:

Código:
char option;
p = new X;
do {
cout << X << endl;
cout << "Te gusta esta clase?" << endl;
cin >> option;
} while(option != 'y');
if(option == 'y') {
hacer algo.....
} else {
delete p;
}
Quisiera saber si hay una forma diferente de hacer eso, ya que si me equivoco y libero la memoria 2 veces da error :S

Gracias!!
  #4 (permalink)  
Antiguo 16/07/2016, 08:50
Avatar de xKuZz  
Fecha de Ingreso: febrero-2015
Ubicación: nullptr
Mensajes: 183
Antigüedad: 9 años, 1 mes
Puntos: 27
Respuesta: Duda con punteros

No vacía el espacio asignado, debes de vaciarlo explícitamente con delete, antes de volver a llamar a new. No obstante, esa metodología a mi punto de vista parece incorrecta por dos razones:
  • Es posible que el compilador optimice el uso de new después de delete y te quedes todo el rato con la misma posición de memoria
  • En caso contrario, estás malgastando tiempo en liberar y reservar memoria y la aleatoriedad de los datos en realidad son datos que fueron usados por otras aplicaciones y procesos del sistema previamente.

Sería, en mi opinión, más correcto realizar lo siguiente:
  • En el constructor por defecto asignar un valor aleatorio a la variable de instancia n. [I]Si no sabes hacerlo basta buscar en Google "numeros aleatorios c++" (o si lo prefieres y puedes la nueva forma de hacerlo de c++11)
  • En vez de realizar delete llamar al constructor por defecto de nuevo de la siguiente manera:

    Código C++:
    Ver original
    1. class X
    2. {
    3. public:
    4.     int n;
    5.   X() {
    6.     // Implementación aleatorio
    7.   }
    8. };
    9.  
    10. int main(int argc, char* args[])
    11. {
    12.     X *p;
    13.     p = new X;
    14.     // Hacer algo
    15.     *p = X(); // Ahora se asignaría un nuevo valor aleatorio a la instancia p de la clase X
    16.     delete p; // Sólo es necesario un delete al final
    17.     return 0;
    18. }
  #5 (permalink)  
Antiguo 16/07/2016, 09:27
Avatar de Andrek  
Fecha de Ingreso: enero-2012
Mensajes: 14
Antigüedad: 12 años, 2 meses
Puntos: 1
Respuesta: Duda con punteros

Wow eso ultimo es lo que necesitaba saber, un metodo diferente y que me parece logico, ya que como lo estaba haciendo funciona pero sentia que no era correcto, por eso pregunte!, GRACIAS HOMBRE!

Si se usar los numero aleatorios, tengo 1 semana con c++ pero siempre habia leido mucho y se mucha teoria pero poca practica, yo programo en Ruby y como entenderas estaba muy acostumbrado a lo automatico, pero me fascina c++ por su precision.

Cambiar el contenido del puntero eso es lo mas correcto, gracias!.
  #6 (permalink)  
Antiguo 18/07/2016, 01:05
 
Fecha de Ingreso: octubre-2014
Ubicación: Madrid
Mensajes: 1.212
Antigüedad: 9 años, 6 meses
Puntos: 204
Respuesta: Duda con punteros

Cita:
Iniciado por xKuZz Ver Mensaje
No obstante, esa metodología a mi punto de vista parece incorrecta por dos razones:
Yo iría un poco más lejos aún.

Si no es estrictamente necesario bien por requisitos de la práctica (vamos, que te exijan hacerlo así), bien por necesidades propias de la aplicación (uso de polimorfismo, variable compartida, ...) yo te recomendaría evitar el uso de punteros en la medida de lo posible.

Evitas fugas de memoria, el programa será más rápido (las reservas de memoria son relativamente lentas), aprovecharás el principio de localidad para mejorar los tiempos de acceso a datos y el programa quedará algo más limpio:

Código C++:
Ver original
  1. int main(int argc, char* args[])
  2. {
  3.     X p;
  4.     // ...
  5.  
  6.     p = X(); // Ahora se asignaría un nuevo valor aleatorio a la instancia p de la clase X
  7.     // ...
  8.  
  9.     return 0;
  10. }

En caso de ser necesario el uso de punteros yo te sugeriría usar los punteros inteligentes. En el caso de un puntero que no vas a compartir lo ideal sería unique_ptr:

Código C++:
Ver original
  1. #include <memory>
  2.  
  3. int main(int argc, char* args[])
  4. {
  5.     std::unique_ptr<X> p(new X());
  6.     // ...
  7.  
  8.     p.reset(new X()); // esta instrucción equivale a delete + new
  9.     // ...
  10.  
  11.     // no hace falta hacer delete
  12.     return 0;
  13. }

Los punteros inteligentes no alteran la forma de acceder al objeto (se sigue usando el operador '->') y ellos solos se encargan de llamar al delete correspondiente cuando proceda:

Código C++:
Ver original
  1. struct POO
  2. {
  3.   POO()
  4.   { var = 1; std::cout << "POO()" << std::endl; }
  5.  
  6.   ~POO()
  7.   { std::cout << "~POO()" << std::endl; }
  8.  
  9.   int var;
  10. }
  11.  
  12. int func()
  13. {
  14.   std::unique_ptr<POO> ptr(new POO);
  15.   std::cout << ptr->var << std::endl;
  16.   // nota que aparecerá el mensaje del destructor pese a no existir ningún delete
  17. }
  18.  
  19. int main()
  20. {
  21.   for( int i=0; i<5; i++ )
  22.     func();
  23. }

Un saludo.
__________________
La ayuda se paga con esfuerzo o con dinero. Si no estás dispuesto a esforzarte y quieres que te hagan los deberes pide presupuesto, al menos así ahorrarás tiempo.

Etiquetas: char, int, memoria, punteros
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 04:59.