Test Foro de elhacker.net SMF 2.1

Programación => Programación C/C++ => Mensaje iniciado por: digimikeh en 23 Febrero 2019, 16:08 PM

Título: punteros como parametros de funciones que no retornan nada... buena idea?
Publicado por: digimikeh en 23 Febrero 2019, 16:08 PM
Según he venido entendiendo hasta ahora, si yo creo un puntero, éste intenta localizar memoria en el espacio dinamico.... estos espacios de memoria deben ser liberados, pero que pasa en el siguiente caso?

Código (cpp) [Seleccionar]

void Persona::IngresarNombre(const char * nombre){
    strcpy(this->nombre, nombre);
   
    delete nombre;   //Es esto necesario?
}



Que sucede con ese puntero a char que está como parámetro?, se elimina solo o yo debo eliminarlo también?

o es mejor idea esto?:

Código (cpp) [Seleccionar]

void Persona::IngresarNombre(const char nombre[16]){
    strcpy(this->nombre, nombre);
}

Gracias.
Título: Re: punteros como parametros de funciones que no retornan nada... buena idea?
Publicado por: K-YreX en 23 Febrero 2019, 16:25 PM
Las dos opciones que tienes son:
Código (cpp) [Seleccionar]

void Persona::IngresarNombre(const char *nombre);

void Persona::IngresarNombre(const char nombre[]);


Y en ambos casos estás haciendo lo mismo. Estás pasando como parámetro la dirección del elemento 0, es decir, el inicio del array en este caso (ya que doy por hecho que ese puntero contiene una cadena/array de caracteres).

No tienes que liberarlo; y te explico. Un puntero se libera con <delete> si se ha usado antes <new> sobre él. Es decir, sólo si estás usando memoria dinámica. En otro caso el puntero se libera solo cuando finaliza la ejecución del programa como cualquier otra variable.
En el caso de que SÍ estés usando memoria dinámica, debes liberar el puntero cuando ya no vayas a usarlo más. Y si has asignado el valor de ese puntero a otro puntero y borras el primero, también estarás borrando el segundo. Ya que lo que haces en realidad es liberar la memoria a la que está apuntando.

Mi recomendación es que no borres el puntero dentro de la función y así te servirá para pasar punteros dinámicos como no dinámicos. Si dentro de la función borras el puntero y en un caso determinado le pasas un puntero no dinámico (osea el comienzo de un array creado sin <new>) tendrás problemas.

Te dejo aquí un par de ejemplos simples para que veas las diferencias :-X:
Código (cpp) [Seleccionar]

int main(){
   char *p_dinamico;
   p_dinamico = new char [20]; // tendras que liberarlo antes de acabar la ejecucion del programa
   char p_estatico[20]; // se liberara solo al acabar

   Persona my_person;
   my_person.InsertarNombre(p_dinamico); // p_dinamico lo puedes liberar en el main mas adelante
   my_person.InsertarNombre(p_estatico); // p_estatico se liberara solo

    delete [] p_dinamico; // como hemos dicho antes
}
Título: Re: punteros como parametros de funciones que no retornan nada... buena idea?
Publicado por: avesudra en 23 Febrero 2019, 16:34 PM
[EDITO] : No había visto el post de YreX-DwX  :-(

Hola digimikeh,

Todo depende de cómo haya sido reservada la memoria a la que apunta el puntero "nombre". Tienes dos casos:

Código (cpp) [Seleccionar]
const char* cadena = "hola"
En éste último caso la duración de esa memoria será hasta el fin de la ejecución de tu programa y no es necesario que la liberes.

Un ejemplo de ambos casos sería(fíjate que cadenaB se libera porque se reservó con new):
Código (cpp) [Seleccionar]

const char* cadenaA = "HOLA";
char* cadenaB = new char[5];
strncpy(cadenaB, cadenaA, 5);

Persona personaA = new Persona();
Persona personaB = new Persona();

personaA.IngresarNombre(cadenaA);

personaB.IngresarNombre(cadenaB);

delete[] cadenaB;


Saludos.
Título: Re: punteros como parametros de funciones que no retornan nada... buena idea?
Publicado por: K-YreX en 23 Febrero 2019, 16:58 PM
Cita de: avesudra en 23 Febrero 2019, 16:34 PM
Código (cpp) [Seleccionar]

const char* cadenaA = "HOLA";
char* cadenaB = new char[5];
strncpy(cadenaB, cadenaA, 5);

Persona personaA = new Persona();
Persona personaB = new Persona();

personaA.IngresarNombre(cadenaA);

personaB.IngresarNombre(cadenaB);

delete[] cadenaB;


Un pequeño apunte. Los objetos de tipo persona los estás creando dinámicamente:
Código (cpp) [Seleccionar]

Persona *personaA = new Persona();
Persona *personaB = new Persona();
// ...
delete personaA;
delete personaB;


Si los creas estáticamente no necesitas usar <new>:
Código (cpp) [Seleccionar]

Persona personaA; // ya llama al constructor sin parametros sin especificarlo nosotros
// ...
// no es necesario liberar memoria ya que no se ha reservado memoria dinamicamente
Título: Re: punteros como parametros de funciones que no retornan nada... buena idea?
Publicado por: avesudra en 23 Febrero 2019, 18:42 PM
Cita de: YreX-DwX en 23 Febrero 2019, 16:58 PM
Un pequeño apunte. Los objetos de tipo persona los estás creando dinámicamente:
Código (cpp) [Seleccionar]

Persona *personaA = new Persona();
Persona *personaB = new Persona();
// ...
delete personaA;
delete personaB;


Si los creas estáticamente no necesitas usar <new>:
Código (cpp) [Seleccionar]

Persona personaA; // ya llama al constructor sin parametros sin especificarlo nosotros
// ...
// no es necesario liberar memoria ya que no se ha reservado memoria dinamicamente


Cierto, se me ha pasado, el copy-paste....

Muchas gracias y saludos.
Título: Re: punteros como parametros de funciones que no retornan nada... buena idea?
Publicado por: digimikeh en 23 Febrero 2019, 20:10 PM
Gracias, hombre, estoy aprendiendo muy rápido en este foro.
Título: Re: punteros como parametros de funciones que no retornan nada... buena idea?
Publicado por: Loretz en 24 Febrero 2019, 02:36 AM
Pregunta:
Es esto necesario?

Citarvoid Persona::IngresarNombre(const char * nombre){
     strcpy(this->nombre, nombre);

     delete nombre;   //Es esto necesario?
}

Respuesta:
¿Cómo saberlo?

Se podría intentar responder primero a algunas cuestiones preliminares, por ejemplo:

¿Está claro en la documentación de cada función que invoca a IngresarNombre() que este parámetro va a ser destruido (delete) (y que cualquiera que vaya a usarla jure primero no volver a usar ese puntero después del punto de llamada).

Este puntero "nombre" ¿fue creado con new? ¿Seguro? (¿no habrá sido con malloc?)

¿No convendría llamar a esta función de alguna manera que deje más claro su comportamiento, por ejemplo,  IngresarNombreYCuidadoQueAcaMuereElPunteroNombre() ?

Cuando una función recibe un puntero "final", se dice que esa función recibe el "ownership", la responsabilidad del "delete", y se la suele llamar "sink function".

Ejemplo:

void sink_f(const char* p) // ¡¡ATENCIÓN!! ESTA FUNCIÓN DESTRUIRÁ A p ¡¡CUIDADO!! ¡¡ALERTA!!
{
    // hacer algo con p, y después
    delete[] p;
}


Y una forma de llamarla sería:

int main()
{
    char* str = new char[12];
    strcpy(str, "hola mundo!");
    sink_f(str);
    // delete[] str; // QUÉ SUERTE QUE LEÍ EL COMENTARIO DE sink_f(), uffff!!

}



Francamente... ¿qué opinas?

Por suerte ya nadie hace cosas como esa, espero.