Operadores new y delete en C++ para memoria dinámica

La asignación de memoria dinámica en C/C++ se refiere a la asignación de memoria realizada manualmente por un programador. La memoria asignada dinámicamente se asigna en Heap, y las variables locales y no estáticas obtienen memoria asignada en Stack (consulte Programas de diseño de memoria C para obtener más detalles).

¿Qué son las aplicaciones? 

  • Un uso de la memoria asignada dinámicamente es asignar memoria de tamaño variable, lo que no es posible con la memoria asignada por el compilador, excepto para arrays de longitud variable .
  • El uso más importante es la flexibilidad proporcionada a los programadores. Somos libres de asignar y desasignar memoria cuando la necesitemos y cuando ya no la necesitemos. Hay muchos casos en los que esta flexibilidad ayuda. Ejemplos de tales casos son Lista enlazada , Árbol , etc.

¿En qué se diferencia de la memoria asignada a las variables normales? 

Para variables normales como «int a», «char str[10]», etc., la memoria se asigna y desasigna automáticamente. Para la memoria asignada dinámicamente como “int *p = new int[10]”, es responsabilidad del programador desasignar la memoria cuando ya no se necesite. Si el programador no desasigna memoria, provoca una fuga de memoria (la memoria no se desasigna hasta que finaliza el programa). 
¿Cómo se asigna/desasigna la memoria en C++?  
C usa la función malloc() y calloc() para asignar memoria dinámicamente en tiempo de ejecución y usa una función free() para liberar memoria asignada dinámicamente. C++ soporta estas funciones y también tiene dos operadores new y delete,que realizan la tarea de asignar y liberar la memoria de una manera mejor y más fácil.

nuevo operador

El nuevo operador denota una solicitud de asignación de memoria en Free Store. Si hay suficiente memoria disponible, un operador new inicializa la memoria y devuelve la dirección de la memoria recién asignada e inicializada a la variable de puntero. 

Sintaxis para usar el operador new

pointer-variable = new data-type;

Aquí, pointer-variable es el puntero de tipo data-type. El tipo de datos podría ser cualquier tipo de datos incorporado, incluida la array, o cualquier tipo de datos definido por el usuario, incluidas la estructura y la clase. 
Ejemplo: 

// Pointer initialized with NULL
// Then request memory for the variable
int *p = NULL; 
p = new int;   

            OR

// Combine declaration of pointer 
// and their assignment
int *p = new int; 

Inicializar memoria: también podemos inicializar la memoria para tipos de datos incorporados usando un nuevo operador. Para tipos de datos personalizados, se requiere un constructor (con el tipo de datos como entrada) para inicializar el valor. Aquí hay un ejemplo de la inicialización de ambos tipos de datos: 

pointer-variable = new data-type(value);

Ejemplo:

int *p = nuevo int(25);
flotante *q = nuevo flotante (75.25);

// Tipo de datos personalizado
struct cust
{
   int p;
   cliente(int q) : p(q) {}
};

// Funciona bien, no requiere constructor
cust* var1 = new cust;    

       O
       
// Funciona bien, no requiere constructor
cust* var1 = new cust();        

// Observe el error si comenta esta línea
cust* var = new cust(25)        

Asignar un bloque de memoria: el operador nuevo también se usa para asignar un bloque (una array) de memoria de tipo tipo de datos

pointer-variable = new data-type[size];

donde tamaño (una variable) especifica el número de elementos en una array. 

Ejemplo:

int *p = new int[10]

Asigna dinámicamente memoria para 10 enteros de forma continua de tipo int y devuelve un puntero al primer elemento de la secuencia, que se asigna arriba (un puntero). p[0] se refiere al primer elemento, p[1] se refiere al segundo elemento, y así sucesivamente. 

dynamic memory allocation

 

Declaración de array normal frente a uso de new 
Hay una diferencia entre declarar una array normal y asignar un bloque de memoria usando new. La diferencia más importante es que el compilador desasigna las arrays normales (si la array es local, se desasigna cuando la función regresa o se completa). Sin embargo, las arrays asignadas dinámicamente siempre permanecen allí hasta que el programador las desasigna o el programa finaliza.
¿Qué pasa si no hay suficiente memoria disponible durante el tiempo de ejecución?  
Si no hay suficiente memoria disponible en el montón para asignar, la nueva solicitud indica un error al lanzar una excepción de tipo std::bad_alloc, a menos que se use «nothrow» con el operador new, en cuyo caso devuelve un puntero NULL (desplácese hasta sección “Manejo de excepciones del operador nuevo” en esteartículo). Por lo tanto, puede ser una buena idea verificar la variable de puntero producida por new antes de usar su programa. 

int *p = new(nothrow) int;
if (!p)
{
   cout << "Memory allocation failed\n";
}

Operador de borrado
Dado que es responsabilidad del programador desasignar la memoria asignada dinámicamente, los programadores cuentan con el operador de borrado en lenguaje C++. 
Sintaxis: 

// Release memory pointed by pointer-variable
delete pointer-variable;  

Aquí, pointer-variable es el puntero que apunta al objeto de datos creado por new
Ejemplos: 

delete p;
delete q;

Para liberar la array asignada dinámicamente a la que apunta la variable de puntero, use la siguiente forma de eliminación

// Release block of memory 
// pointed by pointer-variable
delete[] pointer-variable;  

Example:

   // It will free the entire array
   // pointed by p.
   delete[] p;

CPP

// C++ program to illustrate dynamic allocation
// and deallocation of memory using new and delete
#include <iostream>
using namespace std;
 
int main ()
{
    // Pointer initialization to null
    int* p = NULL;
 
    // Request memory for the variable
    // using new operator
    p = new(nothrow) int;
    if (!p)
        cout << "allocation of memory failed\n";
    else
    {
        // Store value at allocated address
        *p = 29;
        cout << "Value of p: " << *p << endl;
    }
 
    // Request block of memory
    // using new operator
    float *r = new float(75.25);
 
    cout << "Value of r: " << *r << endl;
 
    // Request block of memory of size n
    int n = 5;
    int *q = new(nothrow) int[n];
 
    if (!q)
        cout << "allocation of memory failed\n";
    else
    {
        for (int i = 0; i < n; i++)
            q[i] = i+1;
 
        cout << "Value store in block of memory: ";
        for (int i = 0; i < n; i++)
            cout << q[i] << " ";
    }
 
    // freed the allocated memory
    delete p;
    delete r;
 
    // freed the block of allocated memory
    delete[] q;
 
    return 0;
}

Producción: 

Value of p: 29
Value of r: 75.25
Value store in block of memory: 1 2 3 4 5 

Complejidad de tiempo: O(n), donde n es el tamaño de memoria dado. 

Artículos relacionados:

Este artículo es una contribución de Akash Gupta . Si te gusta GeeksforGeeks y te gustaría contribuir, también puedes escribir un artículo usando write.geeksforgeeks.org o enviar tu artículo por correo a review-team@geeksforgeeks.org. Vea su artículo que aparece en la página principal de GeeksforGeeks y ayude a otros Geeks. Escriba comentarios si encuentra algo incorrecto o si desea compartir más información sobre el tema tratado anteriormente.

Publicación traducida automáticamente

Artículo escrito por GeeksforGeeks-1 y traducido por Barcelona Geeks. The original can be accessed here. Licence: CCBY-SA

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *