Operadores de manejo de memoria new y delete

Veremos su uso en el capítulo de punteros II y en mayor profundidad en el capítulo de clases y en operadores sobrecargados.

Operador new

El operador new sirve para reservar memoria dinámica.

Sintaxis:

[::]new [<emplazamiento>] <tipo> [(<inicialización>)] 
[::]new [<emplazamiento>] (<tipo>) [(<inicialización>)] 
[::]new [<emplazamiento>] <tipo>[<número_elementos>]
[::]new [<emplazamiento>] (<tipo>)[<número_elementos>] 

El operador opcional :: está relacionado con la sobrecarga de operadores, de momento no lo usaremos. Lo mismo se aplica a emplazamiento.

La inicialización, si aparece, se usará para asignar valores iniciales a la memoria reservada con new, pero no puede ser usada con arrays.

Las formas tercera y cuarta se usan para reservar memoria para arrays dinámicos. La memoria reservada con new será válida hasta que se libere con delete o hasta el fin del programa, aunque es aconsejable liberar siempre la memoria reservada con new usando delete. Se considera una práctica muy sospechosa no hacerlo.

Si la reserva de memoria no tuvo éxito, new devuelve un puntero nulo, NULL.

Operador delete

El operador delete se usa para liberar la memoria dinámica reservada con new.

Sintaxis:

[::]delete [<expresión>]
[::]delete[] [<expresión>] 

La expresión será normalmente un puntero, el operador delete[] se usa para liberar memoria de arrays dinámicos.

Es importante liberar siempre usando delete la memoria reservada con new. Existe el peligro de pérdida de memoria si se ignora esta regla.

Cuando se usa el operador delete con un puntero nulo, no se realiza ninguna acción. Esto permite usar el operador delete con punteros sin necesidad de preguntar si es nulo antes.

De todos modos, es buena idea asignar el valor 0 a los punteros que no han sido inicializados y a los que han sido liberados. También es bueno preguntar si un puntero es nulo antes de intentar liberar la memoria dinámica que le fue asignada.

Nota: los operadores new y delete son propios de C++. En C se usan funciones, como malloc y free para reservar y liberar memoria dinámica y liberar un puntero nulo con free suele tener consecuencias desastrosas.

Veamos algunos ejemplos:

int main() { 
   char *c; 
   int *i = NULL; 
   float **f; 
   int n;
 
   // Cadena de 122 más el nulo:
   c = new char[123];
   // Array de 10 punteros a float:
   f = new float *[10]; (1)
   // Cada elemento del array es un array de 10 float 
   for(n = 0; n < 10; n++) f[n] = new float[10]; (2)
   // f es un array de 10*10 
   f[0][0] = 10.32; 
   f[9][9] = 21.39; 
   c[0] = 'a'; 
   c[1] = 0; 
   // liberar memoria dinámica
   for(n = 0; n < 10; n++) delete[] f[n]; 
   delete[] f; 
   delete[] c; 
   delete i; 
   return 0; 
}

Nota: f es un puntero que apunta a un puntero que a su vez apunta a un float. Un puntero puede apuntar a cualquier tipo de variable, incluidos otros punteros.
Este ejemplo nos permite crear arrays dinámicos de dos dimensiones. La línea (1) crea un array de 10 punteros a float. La (2) crea 10 arrays de floats. El comportamiento final de f es el mismo que si lo hubiéramos declarado como:
float f[10][10];

Otro ejemplo:

#include <iostream>
using namespace std;

int main() {
   int *x;
 
   x = new int(67);
   cout << *x << endl;
   delete x;
}

En este caso, reservamos memoria para un entero, se asigna la dirección de la memoria obtenida al puntero x, y además, se asigna el valor 67 al contenido de esa memoria.

Palabras reservadas usadas en este capítulo

delete, new.

Comentarios de los usuarios (11)

Jake
2012-01-04 10:57:25

Hola

Aqui estas usando los punteros a punteros, cuando creo que aun no los has explicado. Esta muy bien el curso.

César Meza
2012-10-15 04:06:47

Excelente curso, es magnifico que te tomes el tiempo para enseñar un poco de tus conocimientos, felicidades por la dedicación.

Antonio
2013-01-15 00:32:01

Hola a todos.

mi duda es la siguiente:

Imaginaros que tengo un texto que cambia constantemente de tamaño en memoria, como en un editor de textos o el registro de sesión del chat de un juego.

el caso es que no conozco la longitud del texto, y por tanto creo un array de forma dinámica:

int tamanyo=100;
char *doc;
doc = mew char[tamanyo];

Pero una vez creado se comporta igual que un array estático, no puedo modificar su longitud.

para poder hacer un array que cambie de tamaño, lo que estoy haciendo es crear una copia, borrar el original y crearlo de nuevo con la nueva longitud, copiar de nuevo los datos y eliminar la copia.

¿hay alguna otra forma de modificar su longitud?

Mi idea es hacerlo sin crear estructuras dinamicas, como las listas, pues aun no las entiendo y me ofrecen demasiado "respeto"...

Gracias.

Arturo
2013-02-18 17:23:34

Para crear un array dinámico, sin tener que destruirlo y volverlo a crear, has de usar vector o list, del espacio de nombres STL

ivan
2013-04-24 01:05:15

que buen curso y exelente pagina agradable a la vista.

Mi pregunta es como hacer que aparesca una imagen en una Windows Application.

Gracias por sus respuestas de antemano.

ivan
2013-04-24 01:16:39

Perdon por la molestia.

Tambien quisiera saber como agregar sonido,video y controlar el teclado o saber que tecla a presionado el usuario, no tiene porque ser una explicasion larga solo un pequeño vistaso.

Gracias por el curso muy bueno.

Salvador Pozo
2013-05-07 18:59:36

Hola, Iván:

Ese tipo de cosas depende en gran medida del sistema operativo, y C++ no tiene soporte nativo para ellas.

En su lugar, tendrás que acceder a bibliotecas externas, distintas en cada sistema.

Por ejemplo, en Windows, tendrás que usar el API. Puedes ver algunas de las funciones para mostrar mapas de bits en:

http://winapi.conclase.net/curso/index.php?cap=023#inicio

Para controlar el teclado:

http://winapi.conclase.net/curso/index.php?cap=034#inicio

Y para el sonido:

http://articulos.conclase.net/?tema=multimedia&art=sonidosapiwin&pag=000

Verás que no se trata de nociones básicas, y necesitarás tener algo de experiencia en programación antes de usar estas funciones.

Hasta pronto.

Borja
2013-05-21 10:50:10

En respuesta a Iván:

La biblioteca SDL integra casi todas esas funciones que necesitas, y también es multiplataforma. En realidad se "apoya" en otras bibliotecas, dependiendo del S.O. para el que se compile el programa (por ejemplo en windows se basa en funciones del GDI de windows o en directx) pero tiene la ventaja de que unifica las funciones por lo que tu código será independiente de la plataforma.

Se suele emplear bastante en programación de videojuegos así que no te costará encontrar tutoriales o información sobre SDL. Tampoco es la única de estas características (hay otras, como Allegro, SFML, etc.) pero posiblemente sea la más utilizada.

Un saludo.

Juan Pablo
2014-11-13 18:04:15

En el último ejemplo haces un acceso al array desde puntero de esta forma:

c[0] = 'a'; 
c[1] = 0; 

Sin embargo en capítulos previos (Punteros 1) solo se explica que la forma de hacerlo sería

*c = 'a';
*(c++) = 0;

¿Esto quiere decir que para acceder al contenido de un array desde un puntero, la forma de hacerlo es también la misma que desde una variable de tipo array?

Carlo
2017-01-11 08:52:54

También tengo esa duda del ultimo comentario, alguien que responda por favor?

Steven R. Davidson
2017-01-11 16:43:41

Hola Carlo,

Existe una correspondencia entre arrays y punteros, por lo que comparten ciertos operadores, ya que ambos conceptos se basan en direcciones de memoria. Hablamos de esta correspondencia en el capítulo anterior ( http://c.conclase.net/curso/index.php?cap=012b#PUNT_Correspondencia ). Respondiendo directamente a la pregunta hecha, sí podemos acceder al contenido apuntado usando el operador * o con el operador []. La diferencia es que el operador [] realiza un cálculo y luego accede al valor apuntado, mientras que el operador * sólo accede al valor apuntado; o sea, no realiza un cálculo.

Espero haber aclarado la duda.

Steven