elhacker.net cabecera Bienvenido(a), Visitante. Por favor Ingresar o Registrarse
¿Perdiste tu email de activación?.

 

 


Tema destacado: Recuerda que debes registrarte en el foro para poder participar (preguntar y responder)


  Mostrar Mensajes
Páginas: 1 ... 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 [79] 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 ... 102
781  Programación / Programación C/C++ / Re: punteros como parametros de funciones que no retornan nada... buena idea? en: 23 Febrero 2019, 16:58 pm
Código
  1. const char* cadenaA = "HOLA";
  2. char* cadenaB = new char[5];
  3. strncpy(cadenaB, cadenaA, 5);
  4.  
  5. Persona personaA = new Persona();
  6. Persona personaB = new Persona();
  7.  
  8. personaA.IngresarNombre(cadenaA);
  9.  
  10. personaB.IngresarNombre(cadenaB);
  11.  
  12. delete[] cadenaB;
  13.  

Un pequeño apunte. Los objetos de tipo persona los estás creando dinámicamente:
Código
  1. Persona *personaA = new Persona();
  2. Persona *personaB = new Persona();
  3. // ...
  4. delete personaA;
  5. delete personaB;

Si los creas estáticamente no necesitas usar <new>:
Código
  1. Persona personaA; // ya llama al constructor sin parametros sin especificarlo nosotros
  2. // ...
  3. // no es necesario liberar memoria ya que no se ha reservado memoria dinamicamente
782  Programación / Programación C/C++ / Re: punteros como parametros de funciones que no retornan nada... buena idea? en: 23 Febrero 2019, 16:25 pm
Las dos opciones que tienes son:
Código
  1. void Persona::IngresarNombre(const char *nombre);
  2.  
  3. 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
  1. int main(){
  2.    char *p_dinamico;
  3.    p_dinamico = new char [20]; // tendras que liberarlo antes de acabar la ejecucion del programa
  4.    char p_estatico[20]; // se liberara solo al acabar
  5.  
  6.    Persona my_person;
  7.    my_person.InsertarNombre(p_dinamico); // p_dinamico lo puedes liberar en el main mas adelante
  8.    my_person.InsertarNombre(p_estatico); // p_estatico se liberara solo
  9.  
  10.    delete [] p_dinamico; // como hemos dicho antes
  11. }
783  Programación / Programación C/C++ / Re: tiene sentido un puntero para uso como arreglo con una dimensión entregada? en: 23 Febrero 2019, 00:30 am
Exacto, mientras estés en una posición de memoria perteneciente a ese programa no, pero si accedes a memoria que no le pertenece te debería saltar un error y no se ejecutaría. Lo que se conoce como "violación de segmento" o "segmentation fault".

Y respecto al array, si lo que quieres es usar un array, tienes que declararlo como un array. Sino sólo estás reservando memoria para un objeto, no para un array de objetos. Y una vez creado mantenerte dentro de los límites para evitar errores en ejecución.  :-X
784  Programación / Programación C/C++ / Re: tiene sentido un puntero para uso como arreglo con una dimensión entregada? en: 22 Febrero 2019, 23:55 pm
Eso es erróneo aunque no aparezca ningún mensaje de error del compilador. Por ejemplo eso era un error que yo veía más en C que trabaja un poco a más bajo nivel que C++...

Un programa reserva memoria para la ejecución completa del mismo. Si no me equivoco, mientras la posición a la que intentas acceder siga dentro del marco de ese programa, no dará error (pero puede ocasionar problemas si tenías otros datos en esa posición). En cambio, cuando la posición sobrepasa los límites de memoria del programa es cuando se sucede un error en tiempo de ejecución para evitar que modifiques un espacio de memoria que puede estar usando tu ordenador para otras cosas.
Si no es exactamente así, pueden corregirme. A mí me suena que era algo así... :-X
785  Programación / Programación C/C++ / Re: Necesito ayuda en: 19 Febrero 2019, 14:29 pm
Además de lo ya comentado no puedes usar <cin> para la entrada de datos. Ya que <cin> sólo almacena hasta el primer espacio. Por lo que si introduces "el nombre" mediante un <cin>, en la variable sólo se almacenará "el".
Para solucionar eso te recomiendo usar <getline()>. Suerte :-X

PD: Si quieres ampliar un poco el programa te recomiendo transformar toda la solución a minúsculas y comparar sólo con "el nombre". Por si se da el caso de que alguien lo escribe en mayúsculas.
786  Programación / Programación C/C++ / Re: Sobrecarga de operador << solo me compila si uso la palabra "friend" en: 13 Febrero 2019, 18:51 pm
Estuve observando el ostream que mencionas, pero por mas que veo, se me pasa el error, no lo veo, en qué linea está ?..

En tu fichero Persona.cpp en la declaración de la sobrecarga del operador <<. Y si lo quieres ver en el primer mensaje de este tema, el segundo bloque de código:
Código
  1. //Persona.cpp
  2.  
  3. #include "Persona.h"
  4.  
  5. using namespace std;
  6.  
  7. //Sobrecarga operador
  8. ostring & operator<<(ostring & os, const Persona & _estaPersona){
  9.     os << "Nombre : " << _estaPersona.LeerNombre() << endl;
  10.     os << "Edad     : " << _estaPersona.LeerEdad() << endl;
  11.     return os;
  12. }
  13.  
787  Programación / Programación C/C++ / Re: Punteros fantasmas... (asi le puse yo).. en: 13 Febrero 2019, 05:13 am
Exacto, sobra el reservar memoria en el <main>. Imagina que cuando usas <new> compras un almacén para guardar "datos" y cuando ya no lo necesitas usas <delete> para venderlo. Un puntero guarda la dirección del almacén.

En tu caso la función <sumar()> compra un almacén, guarda la suma en él y te envía la dirección donde tienes tu almacén. Entonces en el <main> lo que haces es guardar la dirección que te envía la función <sumar()> en el puntero nuevo. No necesitas comprar otro almacén. Porque si compras otro almacén en el <main> y donde tienes guardada la dirección del nuevo almacén, guardas la dirección del almacén que compraste en la función <sumar()>, ya no sabes donde está el último almacén que has comprado. Y si no sabes donde lo tienes, no puedes venderlo... :-\

No sé si queda claro con esto pero es el mejor símil que se me ha ocurrido :-X
788  Programación / Programación C/C++ / Re: Sobrecarga de operador << solo me compila si uso la palabra "friend" en: 13 Febrero 2019, 05:02 am
Este es un error típico con la sobrecarga tanto del operador << como del operador >>.
Ambas sobrecargas son funciones, no métodos. Un método de una clase puede acceder a los miembros privados por si sólo porque en eso consiste un método, en una función que pertenece a una clase.

Sin embargo, esa sobrecarga es una función, no un método. Entonces el prototipo de la función debe definirse fuera de la clase. Y la implementación de la función si se hace en un fichero distinto se hace sin referenciar la clase a la que pertenece (ya que no pertenece a ninguna).

Y cuando queremos hacer que una función sea "friend" entonces el prototipo lo incluimos dentro de la clase precedido de la palabra <friend> pero si no se usa la palabra <friend> entonces hay que declararlo fuera de la clase.

Código
  1. class MiClase{
  2.    private:
  3.        // miembros y metodos privados
  4.    public:
  5.        // miembros y metodos publicos
  6.        // Opcion 1: sobrecarga con friend
  7.        friend std::ostream& operator<<(ostream&, const MiClase&);
  8. };
  9. // Opcion 2: sobrecarga sin friend
  10. std::ostream& operator<<(ostream&, const MiClase&);

Espero haber resuelto tus dudas respecto a este tema. Suerte :-X

PD: He visto un extraño <ostring> en tu código... :silbar:
789  Programación / Programación C/C++ / Re: Punteros fantasmas... (asi le puse yo).. en: 11 Febrero 2019, 19:39 pm
Se eliminan ambos y ahora te explico.
Cuando se elimina un puntero, no eliminas el puntero como tal, sino que liberas la memoria a la que apunta el puntero. Cuando asignas un puntero a otro, ambos apuntan a la misma dirección de memoria. Entonces con eliminar uno de los dos, ya queda liberada la memoria.

Código
  1. int* sumar(int a, int b){
  2.    int *suma = new int(a+b); // reservas memoria para un entero
  3.    return suma;
  4. }
  5.  
  6. int main(){
  7.    int *psuma = sumar(2,2); // psuma apunta a la misma memoria que apuntaba suma
  8.    delete psuma; // liberamos la memoria a la que apunta psuma que es la misma que suma
  9. }
790  Programación / Programación C/C++ / Re: Punteros fantasmas... (asi le puse yo).. en: 11 Febrero 2019, 17:48 pm
Hola!
Me he topado con el siguiente escenario:
Código
  1. //En este fragmento al terminar la función, se destruye el contenido de suma y retorna null o vacío, y el puntero suma sigue existiendo en memoria....
  2. int RetornaUnaSuma(int a, int b){
  3.     int * suma = new int;
  4.     *suma = a+b;
  5.     return *suma;
  6. }
  7. //Aqui intento retornar un puntero creado dentro de la misma función...
  8. int * RetornaUnaSuma(int a, int b){
  9.     int * suma = new int;
  10.     *suma = a+b;
  11.     return suma;
  12.     //pero al terminar la función, se destruye el contenido y retorna una dirección de memoria sin contenido, el puntero sigue existiendo..
  13. }
  14.  
Según yo es mala práctica declarar punteros que quieras retomar dentro de una función o un ámbito...  bueno aparte de mala practica no funciona el retorno...Es como lo pienso?...
Probablemente se pueda devolver punteros cuando éstos mismos ingresan como argumento...
La función sería:
Código
  1. //Segun yo esto debe funcionar...
  2. int * RetornaUnaSuma(int * pSuma, int a, int b){
  3.     *pSuma = a+b;
  4.     return pSuma;
  5. }
  6.  
Que opinan...
Saludos.

Respecto al primer mensaje, te dejo tres variantes para analizar cada una de ellas.
  • Variante 1
    La más simple, una función que suma los parámetros en un entero y lo retorna.
    Código
    1. int sumar(int a, int b){
    2.    int suma = a + b;
    3.    return suma;
    4. }
    En este caso no hay mucha complicación, la variable <suma> que es de ámbito local se destruye al terminar la función.

  • Variante 2
    Usando punteros. Creamos un puntero a entero donde se va a guardar la suma y retornamos el puntero .
    Código
    1. int* sumar(int a, int b){
    2.    int *psuma = new int (a + b);
    3.    return psuma;
    4. }
    En este caso como estamos usando memoria dinámica al usar <new>, tenemos que liberar luego la memoria con <delete>. Como la función retorna el puntero no hay problema porque esa función se tiene que asignar a un puntero a entero en otro sitio (ya sea en el <main> o en otra función). Entonces liberamos la memoria en ese sitio:
    Código
    1. int main(){
    2.    int *psuma = sumar(2,2);
    3.    // usas el puntero psuma
    4.    delete psuma;
    5. }

  • Variante 3
    Esto es lo que has implementado en primer lugar y la opción más rara y menos apropiada. Crear un putero a entero donde guardar la suma y retornar el valor de la suma .
    Código
    1. int sumar(int a, int b){
    2.    int *psuma = new int (a + b);
    3.    return *psuma;
    4. }
    En este caso tenemos un problema con la memoria dinámica. Una de las cosas que tiene la memoria dinámica es que cuando se crea un objeto/variable usando esta, el objeto/variable siempre debe estar apuntado por algún puntero. Si deja de ser apuntado por alguien, se pierde. Entonces aquí cuando acaba la función retorna el valor de la suma, el cual es correcto, pero se pierde el puntero <psuma> por lo que ya no se puede liberar.
    Código
    1. int main(){
    2.    int suma = sumar(2,2);
    3.    // usamos la variable suma pero...
    4.    // hemos perdido el puntero local de la funcion
    5. }

    Si quieres profundizar un poco el tema de los valores de retorno, que se guarde temporalmente el valor que se devuelve antes de ser destruido puedes indagar un poco dentro del lenguaje ensamblador. Puedes ver una llamada a función sencilla como esta para ver como la función guarda en un registro el valor de retorno. Entonces cuando la función ha acabado, el valor de retorno está guardado en un registro que debe ser guardado en otro sitio antes de volver a usar ese registro, por eso hay que asignarlo a una variable. Suerte :-X
Páginas: 1 ... 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 [79] 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 ... 102
WAP2 - Aviso Legal - Powered by SMF 1.1.21 | SMF © 2006-2008, Simple Machines