Usar malloc vs new asignadores en C++

Jinku Hu 12 octubre 2023
  1. Usar el operador new para asignar la memoria dinámica en C++
  2. Usa el operador new y std::unique_ptr para asignar la memoria dinámica en C++
  3. Usa la función malloc y realloc/reallocarray para asignar la memoria dinámica
Usar malloc vs new asignadores en C++

Este artículo explicará varios métodos de uso de los asignadores de malloc vs. new en C++.

Usar el operador new para asignar la memoria dinámica en C++

new es la interfaz preferida para manejar la memoria dinámica en C++ directamente. Construye un objeto del tipo dado y le devuelve el puntero. Los objetos asignados usando el operador new son inicializados por defecto, lo que significa que los objetos de tipo incorporado y compuesto tienen valores basura que necesitan ser inicializados antes de ser usados.

Note que new puede ser llamado con múltiples notaciones para satisfacer diferentes necesidades, pero en el siguiente ejemplo, asignamos el array int de tamaño 10. Así, el puntero devuelto almacenado en la variable arr1 apunta al trozo de memoria que es de 40 bytes. La función initPrintIntVector sólo se implementa para demostrar mejor un ejemplo práctico de codificación. Ya que estamos usando el llamado puntero desnudo, es importante liberar la memoria asignada con el operador delete antes de que el programa salga. Sin embargo, los corchetes después del delete también son necesarios para distribuir cada posición en el array.

#include <iomanip>
#include <iostream>
#include <random>
#include <vector>

using std::cout;
using std::endl;
using std::setw;
using std::vector;

constexpr int SIZE = 10;
constexpr int NEW_SIZE = 20;
constexpr int MIN = 1;
constexpr int MAX = 1000;

void initPrintIntVector(int *arr, const int &size) {
  std::random_device rd;
  std::default_random_engine eng(rd());
  std::uniform_int_distribution<int> distr(MIN, MAX);

  for (int i = 0; i < size; ++i) {
    arr[i] = distr(eng) % 1000;
    cout << setw(2) << arr[i] << "; ";
  }
  cout << endl;
}

int main() {
  int *arr1 = new int[SIZE];

  initPrintIntVector(arr1, SIZE);

  delete[] arr1;
  return EXIT_SUCCESS;
}

Resultado (*aleatorio):

 8; 380; 519; 536; 408; 666; 382; 244; 448; 165;

Usa el operador new y std::unique_ptr para asignar la memoria dinámica en C++

Aunque el new operador parece ser una buena herramienta para la asignación dinámica de la memoria, puede ser bastante propenso a errores en las grandes bases de código con manipulaciones intensivas de la memoria. A saber, la asignación de los recursos de memoria en el momento adecuado es un problema bastante difícil de abordar, y en su mayoría resulta en fugas de memoria o errores de ejecución inesperados. Por eso la biblioteca estándar, desde la versión C++ 11 añadió punteros inteligentes que borran automáticamente la memoria a la que apuntan. std::unique_ptr es un tipo de puntero inteligente, que sólo se permite a sí mismo apuntar al objeto dado. Nótese que la asignación se sigue haciendo usando el operador new, y después de que el puntero haya sido usado podemos salir del programa sin llamar a delete.

#include <iomanip>
#include <iostream>
#include <random>
#include <vector>

using std::cout;
using std::endl;
using std::setw;
using std::vector;

constexpr int SIZE = 10;
constexpr int NEW_SIZE = 20;
constexpr int MIN = 1;
constexpr int MAX = 1000;

void initPrintIntVector(int *arr, const int &size) {
  std::random_device rd;
  std::default_random_engine eng(rd());
  std::uniform_int_distribution<int> distr(MIN, MAX);

  for (int i = 0; i < size; ++i) {
    arr[i] = distr(eng) % 1000;
    cout << setw(2) << arr[i] << "; ";
  }
  cout << endl;
}

int main() {
  std::unique_ptr<int[]> arr2(new int[SIZE]);

  initPrintIntVector(arr2.get(), SIZE);

  return EXIT_SUCCESS;
}

Producción :

985; 885; 622; 899; 616; 882; 117; 121; 354; 918;

Usa la función malloc y realloc/reallocarray para asignar la memoria dinámica

Por otro lado, el código C++ puede llamar a la función asignadora original de estilo C - malloc, que es una forma bastante arcaica de manipulación de la memoria dinámica para los estándares modernos de C++. No es la forma recomendada de asignar objetos en el montón, pero en el lado positivo, malloc proporciona una funcionalidad más flexible.

Se llama a malloc con un solo argumento que especifica el sizeof del objeto y devuelve el void* que debe ser lanzado al tipo correspondiente en C++. La única ventaja de la memoria asignada a malloc es que puede ser expandida/contraída por la función realloc o reallocarray. La función realloc toma el puntero al objeto y el nuevo tamaño como argumentos, mientras que reallocarray toma el puntero, el número de elementos y el tamaño de cada elemento. Observe que si la memoria del objeto se expande, los antiguos valores almacenados permanecen intactos, y los elementos recién añadidos no se inicializan. Por lo tanto, el siguiente ejemplo imprime los elementos arr3 expandidos sólo con fines de demostración, y no debería ser el caso en el programa del mundo real.

#include <iomanip>
#include <iostream>
#include <random>
#include <vector>

using std::cout;
using std::endl;
using std::setw;
using std::vector;

constexpr int SIZE = 10;
constexpr int NEW_SIZE = 20;
constexpr int MIN = 1;
constexpr int MAX = 1000;

void initPrintIntVector(int *arr, const int &size) {
  std::random_device rd;
  std::default_random_engine eng(rd());
  std::uniform_int_distribution<int> distr(MIN, MAX);

  for (int i = 0; i < size; ++i) {
    arr[i] = distr(eng) % 1000;
    cout << setw(2) << arr[i] << "; ";
  }
  cout << endl;
}

void printIntVector(int *arr, const int &size) {
  for (int i = 0; i < size; ++i) {
    cout << setw(2) << arr[i] << "; ";
  }
  cout << endl;
}

int main() {
  int *arr3 = static_cast<int *>(malloc(SIZE * sizeof(int)));
  //    int *arr3 = static_cast<int *>(malloc(SIZE * sizeof *arr3));
  //    int *arr3 = static_cast<int *>(malloc(sizeof(int[SIZE])));

  initPrintIntVector(arr3, SIZE);

  arr3 = static_cast<int *>(reallocarray(arr3, NEW_SIZE, sizeof(int)));
  // arr3 = static_cast<int *>(realloc(arr3, NEW_SIZE * sizeof(int)));
  printIntVector(arr3, NEW_SIZE);

  free(arr3);
  return EXIT_SUCCESS;
}

Producción :

128; 346; 823; 134; 523; 487; 370; 584; 730; 268;
128; 346; 823; 134; 523; 487; 370; 584; 730; 268;  0;  0;  0;  0;  0;  0;  0;  0;  0;  0;
Autor: Jinku Hu
Jinku Hu avatar Jinku Hu avatar

Founder of DelftStack.com. Jinku has worked in the robotics and automotive industries for over 8 years. He sharpened his coding skills when he needed to do the automatic testing, data collection from remote servers and report creation from the endurance test. He is from an electrical/electronics engineering background but has expanded his interest to embedded electronics, embedded programming and front-/back-end programming.

LinkedIn Facebook

Artículo relacionado - C++ Memory