Memoria dinamica?

Iniciado por vangodp, 29 Abril 2014, 16:17 PM

0 Miembros y 1 Visitante están viendo este tema.

vangodp

bueno compañeros =D

Llevo ya algún tiempo leyendo lo de cpp tal y tal, algunas cosas las he comprendido otras no tanto, pero ya me muevo algo.
Cosas como clases, punteros, algo de herencia y polimorfismo, tablas y tablas multi dimensionales...
Algunas cosas me quedaron claras otras menos y algunas se me van olvidar que le voy hacer.
Si hay una cosa que he ido dejando palante palante es la memoria dinámica.  :xD
Claro que la he leído y se declarar un int con el puntero y new... Cosillas pequeñas aparte soy partidario de cpp, se que se usa new y el delete para crear y liberar lo normalito.
Os diré lo que se y si me pueden arroyar algo de luz seré muy feliz  ;D
Se que en cpp se usa el new y el delete, en c se usa alloc, malloc y otros, pero nunca los use. En c se puede redimensionar las tablas "creo"...con ralloc. ¿No?
Hasta aquí nada nuevo.
Ha llegado el día que yo harto cardo me he armado de valor para intentar entender eso. =D
Así que cualquier cosita que me esclarezca es bienvenida y ya me apañare para aprender, necesito consejillos vamos.
¿Es mejor usar c o c++ para la memoria dinámica?Digo por que lo que tengo son mas preguntas que respuestas.
¿En c++ alloc permite crear objetos no típicos de c como clases?
¿Las tablas se pueden redimensionar usando new y delete de cpp? Dicen algunos que use la clase vector solamente¿Es que no hay otra forma forma? =(
¿Es verdad que no se puede mezclar esas cosillas XDD??
En fin...¿Cual es mejor  y por que lo es  o para que es mejor cada cosa?

Gracias de antemano chicos. ¡Mucha suerte! ^^



eferion

Cita de: vangodp en 29 Abril 2014, 16:17 PM
¿Es mejor usar c o c++ para la memoria dinámica?Digo por que lo que tengo son mas preguntas que respuestas.

Si estás programando en C, usa las funciones de C... si estás en C++, usa new y delete.

internamente, new llama a malloc y después llama al constructor de la clase. Hasta aquí nada nuevo. La potencia real de usar new es que puedes "customizar" la forma en la que se hacen las reservas de memoria para optimizar el proceso.

No olvidemos que malloc está pensado para hacer reservas grandes de memoria... con reservas pequeñas es altamente ineficiente.

Una inmejorable reseña sobre este tema se puede encontrar en el tema 4 del libro: "Modern C++ Design", de Andrei Alexandrescu

Cita de: vangodp en 29 Abril 2014, 16:17 PM
¿En c++ alloc permite crear objetos no típicos de c como clases?

malloc o calloc únicamente reservan memoria, como te he comentado en el punto anterior, "new" se encarga de llamar al constructor correspondiente para inicializar correctamente el objeto.

Cita de: vangodp en 29 Abril 2014, 16:17 PM
¿Las tablas se pueden redimensionar usando new y delete de cpp? Dicen algunos que use la clase vector solamente¿Es que no hay otra forma forma? =(

new y delete, como tales, no permiten hacer realloc, al menos que yo sepa.

Lo que sucede es que C++ te permite encapsular operaciones de realloc dentro de una clase, por lo que desde fuera es algo que te resulta transparente.

La gracia de usar contenedores en vez de memoria dinámica "a pelo" es que puedes delegar parte del trabajo. Los contenedores ya implementan la lógica necesaria para evitar lagunas de memoria... obviamente puedes gestionar la memoria tu directamente, pero tendrás que reinventar la rueda.

Es importante recordar que la programación, contra creencia popular de los ignorantes, es un trabajo bastante laborioso... todo lo que puedas evitar reescribir bienvenido sea ( te ahorras tiempo, dinero y bugs ).

Cita de: vangodp en 29 Abril 2014, 16:17 PM
¿Es verdad que no se puede mezclar esas cosillas XDD??

A estas alturas ya sabrás que "new" hace un "malloc" por detrás, al igual que "delete" hace un "free"... lo que sucede es que estos usos estan "centralizados".

Lo que sí es importante es recordar que "al cesar lo que es del cesar", es decir, si reservas con malloc, liberas con free... y si creas con new... lo eliminas con delete, cualquier otra combinación puede ser potencialmente peligrosa.

Dicho esto, el mayor problema de mezclar en tu código instrucciones new con malloc es que luego tienes que asignar correctamente los free y los delete... ¿por qué te vas a complicar la vida de forma gratuíta?

Cita de: vangodp en 29 Abril 2014, 16:17 PM
En fin...¿Cual es mejor  y por que lo es  o para que es mejor cada cosa?

Volviendo a mi primera respuesta:

"Si estás programando en C, usa malloc, calloc y realloc... si estás en C++, usa new y delete"

Cita de: vangodp en 29 Abril 2014, 16:17 PM
Gracias de antemano chicos. ¡Mucha suerte! ^^

Un placer ser de utilidad.

Un saludo.

vangodp

¡Pues gracias eferion!
A new y delete pues me pegare.
Para arrays mejor son los contenedores(vectores, listas y mapas) ya te hacen el trabajo sucio digamos  :laugh:
Intento quedar siempre con c++ puro pero as veces me gusta saber al menos como funcionan XDD
¡Saludos y mucha suerte!  ;-)

eferion

Es mas impprtante, desde mi punto de vista, saber como funcionan las cosas a saber aprovechar al máximo las características del lenguaje.

Sabiendo como funcionan puedes adaptarte a nuevas necesidades... Si no lo sabes mas vale que conozcas alguna utilidad que sirva para tus necesidades...

vangodp

Esos consejos son los que me gusta escuchar =D
En todo hay cosas que te facilitan la vida pero lo que me intriga, por ejemplo en un ordenador es la tripa no la caja  :laugh:
De pequeño me daban juguetes, a la hora o por ahí ya me iba a por la caja de herramienta de mi padre a destrozarlo todo jajaja, nunca los conseguía montar por supuesto. :-(
Pues con la programación es lo mismo, quiero saber como funcionan algunas cosas para saber el por que tomar un determinado camino aun que lo jod... jajaj.
Saludos^^

amchacon

A ver, hacer una función para redimensionar el array no es muy díficil:
Código (cpp) [Seleccionar]
#include <iostream>
using namespace std;

template<class T>
void Realloc(T* &array,int tam,int tam_final)
{
   if (tam_final < tam) // se reduce el array
   {
       for (int i = tam;i >= tam_final;i--) delete &array[i];
   }
   else if (tam_final > tam) //se aumenta el array
   {
       T* aux = new T[tam_final](); // creo un array nuevo

       for (int i = 0; i < tam;i++)
       {
           aux[i] = array[i]; // copio el contenido del array anterior
       }

       delete[] array; // borro el array viejo

       array = aux; // el puntero apunta al nuevo array
   }
}

int main()
{
   int* array = new int[4];

   for (int i = 0; i < 4;i++) array[i] = i+1;

   Realloc(array,4,10); // redimensiono el array de 4 a 10

   array[6] = 3; // puedo hacerlo porque he redimensionado el array ^^

   return 0;
}


Por cierto un puntero inicializado con new no puede ser borrado con free (o al menos, el estándar no te lo garantiza que funcione).
Por favor, no me manden MP con dudas. Usen el foro, gracias.

¡Visita mi programa estrella!

Rar File Missing: Esteganografía en un Rar

vangodp

 :o ¿Así es como lo redimensionamos?
Pasando de uno mas pequeño a uno mas grande y al revés  O_o
¿Se hace de forma rápida o puede ser lento el proceso si la tabla es algo grande?
Al final me voy a pegar al pushback XDD
(y) gracias!

amchacon

#7
No haber son dos casos, el primero es cuando queremos reducir el array y el segundo es cuando queremos aumentarlo. O una cosa o la otra xD.

Push_back hace algo parecido, aunque vector optimiza un poco el proceso reservando memoria de más. En vez de ir aumentando el vector de uno en uno pues lo aumenta de 10 en 10, asi los siguientes 9 push_back no precisan de otro realloc, que es una operación relativamente costosa.
Por favor, no me manden MP con dudas. Usen el foro, gracias.

¡Visita mi programa estrella!

Rar File Missing: Esteganografía en un Rar

vangodp

Buenas!!  ::)
Bueno ya que me has empicado me vas a tener que ayudar jejej
Como aun no se na de template ni lo que hacen no se que hace T* &array de void Realloc(T* &array,int tam,int tam_final)

¿¿espera una plantilla??La cosa es que aun no llegue a tanto jeje :laugh:
Como ves estoy aun en las tablitas del colegio primario ^^ :laugh:
Salu

eferion

Cita de: vangodp en 30 Abril 2014, 11:54 AM
Como aun no se na de template ...

Un template es una plantilla. Las plantillas son como prototipos de clases... están incompletas. Un template sirve para crear una clase genérica ( como un contenedor ). Digo genérica porque hay tipos que se dejan abstractos, en el caso del ejemplo de amchacon, la famosa "class T".

El compilador, cuando se encuentra con un template, digamos que lo "memoriza", pero no lo compila ( no puede porque la clase no está completamente definida). Cada vez que encuentra un uso de ese template, revisa su lista de clases. Si aún no existe una especialización del template para esa clase, compila una versión personalizada del template, en caso contrario, se limita a enlazar con la versión compilada anteriormente.

Es decir. Si tu tienes un código tal que:

Código (cpp) [Seleccionar]

std::vector< int > intVector;
std::vector< bool > boolVector;


El compilador va a crear dos versiones especializadas del template, una en la que sustituye "T" por "int", y otra en la que lo sustituye por "bool". Al ser clases independientes, no puedes tirar de "herencia" para tratar los diferentes tipos de vectores de forma genérica.

Esto no puedes hacerlo:

Código (cpp) [Seleccionar]

std::vector< T >* intVector = new std::vector< int >( );
std::vector< T >* floatVector = new std::vector< float >( );


Realmente, cada versión de "vector" es completamente independiente de las demás, no comparten nada de código ( cada versión está adaptada a los tipos concretos que usa esa versión ).

El tema de los templates da para escribir durante varias horas... es mejor que también trastees un poco por la red por tires de manuales que tengas en casa. Si bien es cierto que se pueden hacer auténticas maravillas con los templates, también es cierto que abusar de ellos sin control puede complicar demasiado el mantenimiento del código. Estás avisado.

Cita de: vangodp en 30 Abril 2014, 11:54 AM
... ni lo que hacen no se que hace T* &array de void Realloc(T* &array,int tam,int tam_final)

Como te comenté, los templates son clases "incompletas", en este caso concreto, se define un tipo T que es indefinido.

La llamada que no entiendes, "T* &array", lo que hace es definir una suerte de puntero doble... solo que usando sintaxis propia de C++. Bueno, la definición real sería un puntero a una referencia. La idea de usar un puntero doble es que te permite modificar la posición a la que apunta "array", desde dentro de la función, por lo que el realloc es transparente para ti.

Sin el puntero doble, podrías modificar el contenido de la memoria apuntada por "array", pero no podrías reubicar ese contenido en el mapa de memoria del programa.