Objetos y Punteros en C++
Hola llevo poco tiempo programando en C++. Y bueno aun no tengo claro la idea de cuando usar punteros y cuando usar objetos. Porque por ejemplo uno podría crear una clase en C++ y luego crear un puntero que haga referencia a dicha clase; sin embargo, tambien podria instanciar la clase con un objeto, de esta forma por ejemplo:
ifstream in;
que vendria a ser diferente a hacer:
ifstream *in = new ifstream;
Entonces, ¿cuando usar la primera opcion y cuando la segunda?, porque cuando uso la primera, ya no tengo que preocuparme por liberar memoria, ¿no?
Gracias por su respuesta.
Saludos.
¿Existe algun sitio web o libro de donde pueda obtener mas informacion sobre esto?
Agradecería me las hiciera saber; por lo demas, bastante clara la explicación.
Gracias 
1. ifstream in;
El objeto in permanecerá en memoria hasta que termine el bloque en el que se encuentra declarado, esto es, hasta el final de la función (en el '}' de la función o cuando se ejecuta un return) que lo contiene o hasta el fin del programa si se trata de una variable global. En ese momento se llamará a su destructor y la memoria del objeto ya no estará disponible, de eso se encarga el compilador.
La variable in siempre referenciará al mismo objeto por más que se le asigne otro objeto.
2 ifstream *in = new ifstream;
El objeto puede ser destruido y la memoria liberada en cualquier momento con delete. La liberación de memoria ya no se realiza automáticamente sino que se debe indicar explícitamente en el código.
El puntero in puede referenciar a otros objetos pero solo uno a la vez.
ifstream uno, dos, tres;
in = &uno; // in referencia al objeto uno
in = &dos; // in referencia al objeto dos
in = &tres; // in referencia al objeto tres
Osea, que el primer caso es para trabajar con una cantidad fija de datos y/o cuando los objetos son siempre los mismos. El segundo caso es para tratar con datos dinámicos y/o con diferentes objetos realizando las mismas operaciones.
En realidad en los 2 casos estas usando objetos, el uso es diferente, pues si creaste
ifstream in; //si se crea en una función es una variable temporal
podrías usar :
ifstream * pin = ∈
y obtienes el mismo resultado, lo que los diferencia es el uso que les puedas dar, por ejemplo creando por el new le asignas memoria y sabrás que tratando con un puntero a ese objeto desde cualquier lugar del código lo podrás modificar y también te aseguras que en ningún momento se destruirá.
Ahora cuando creas objetos por el método NEW te tienes que asegurar que estás borrando los objetos que creaste cuando ya no los necesites.
Saludos
















Basicamente la pregunta que te planteas tiene que ver con la forma en como un programa usa la memoria para almacenar sus datos. Todo programa ejecutable cuando se esta compilando sabe cuanta memoria va a ocupar los datos que usara, por lo que cuando el programa ya esta compilado y se desea ejecutar, el sistema operativo sabe cuanto va a ocupar y por lo tanto le determina un lugar en la memoria en donde resida para su ejecucion. Pero esto es estatico (por eso se le llama asignacion de memoria estatica), osea una vez que el programa ya se compilo, este tamaño no va a cambiar nunca, a menos que cambies el codigo y compiles de nuevo. La asignacion estatica la constituyen todos los objetos o variables que estan dentro de tu programa. Por ejemplo la instruccion
Persona p; //donde Persona es una clase que define algunos campos
Cuando tu programa se compila, el compilador detecta que este objeto debe formar parte de la memoria asignada a tu programa, por lo que todo el objeto p, estara en el bloque de memoria dentro de tu programa. Ademas si imprimes el tamaño del objeto (sizeof(p)) eso te da cuantos bytes ocupa el objeto p en la memoria, lo cual depende de cuanta informacion haya dentro del objeto.
Pero cuando defines
Persona* p = new Persona;
La cosa cambia. En principio lo que el compilador ve no es un objeto, es un puntero a un objeto, una referencia, un numero que indica donde esta el objeto real. De hecho, el compilador solo asignara a tu programa un espacio de memoria en donde va a ir esa direccion (ojo!! no el objeto). Entonces, donde esta el objeto? La instruccion new en tiempo de ejecucion hace lo siguiente: Se crea un objeto de tipo Persona en el heap (porcion de memoria disponible justamente para que los programas hagan uso de ella, como se les antoje :) ), si hay memoria disponible en el heap, coloca el nuevo objeto en el heap y devuelve la direccion de memoria en donde lo coloco y la guarda en la variable p. Osea p lo que almacena es un numero( de hecho siempre un numero entero). Lo puedes comprobar imprimiendo solamente p asi:
cout<<p<<endl; // Saldra un numero entero expresado en hexadecimal
Y aun mas interesante si imprimes:
cout<<sizeof(p)<<endl;
imprimira 4. Pero porque? Justamente p es un numero, una direccion del objeto al que referencia. Cabe recalcar que el heap es una porcion de memoria compartida por todos los programas.
A este tipo de asignacion de memoria se le llama dinamica, porque en realidad no depende del tamaño de memoria asignada a tu programa, sino de cuanta memoria disponible haya en el heap. Y siempre tu programa mantiene su mismo tamaño.
Y cuando empleas un objeto, no liberas memoria, porque cuando tu programa termina, el sistema operativo se encarga de limpiar el espacio en donde estaba, con todo y sus datos. Pero cuando creas objetos en el heap, cuando el programa termina, el sistema operativo no tiene forma de saber en donde estan los objetos que tu programa usa, por lo que queda como responsabilidad del programador.
Lo bueno de emplear memoria dinamica es que tu programa puede usar toda la memoria que quiera sin necesidad de que tu programa en si se convierta en un monstruo que no quepa en memoria, ademas lo bueno es que no todos los objetos que usa tu programa deben estar juntos en el heap, lo que posibilita que se emple la memoria mas eficientemente. Es por eso muy comun este tipo de asignacion en la creacion de estructuras de datos, ya que no necesariamente los componentes de esta tienen que estar juntos, lo que potencia su crecimiento y su utilizacion.
Espero haber ayudado en algo a tu duda.
Saludos.
Iván Sipirán Mendoza
Estudiante de Doctorado en Ciencias de la Computación
Universidad de Chile