Usa malloc rispetto ai new allocatori in C++

Jinku Hu 12 ottobre 2023
  1. Usa il new operatore per allocare la memoria dinamica in C++
  2. Usa il new operatore e std::unique_ptr per allocare la memoria dinamica in C++
  3. Usa la funzione malloc e realloc / reallocarray per allocare la memoria dinamica
Usa malloc rispetto ai new allocatori in C++

Questo articolo spiegherà diversi metodi per usare gli allocatori malloc e new in C++.

Usa il new operatore per allocare la memoria dinamica in C++

new è l’interfaccia preferita per gestire direttamente la memoria dinamica in C++. Costruisce un oggetto del tipo dato e gli restituisce il puntatore. Gli oggetti allocati usando l’operatore new sono inizializzati di default, il che significa che gli oggetti di tipo composto e incorporati hanno valori di spazzatura che devono essere inizializzati prima dell’uso.

Nota che new può essere chiamato con più notazioni per soddisfare esigenze diverse, ma nel seguente esempio, allochiamo l’array int di dimensione 10. Pertanto, il puntatore restituito memorizzato nella variabile arr1 punta al blocco di memoria che è 40 byte. La funzione initPrintIntVector è implementata solo per dimostrare meglio un esempio pratico di codifica. Dato che stiamo usando un cosiddetto puntatore nudo, è importante liberare la memoria allocata con l’operatore delete prima che il programma esca. Attenzione però, le parentesi dopo il delete sono necessarie anche per deallocare ogni posizione nell’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;
}

Uscita (* casuale):

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

Usa il new operatore e std::unique_ptr per allocare la memoria dinamica in C++

Anche se il new operatore sembra essere un ottimo strumento per l’allocazione dinamica della memoria, può diventare piuttosto soggetto a errori nelle grandi basi di codice con manipolazioni intense della memoria. Vale a dire, la deallocazione delle risorse di memoria al momento giusto è un problema piuttosto difficile da affrontare e principalmente si traduce in perdite di memoria o errori imprevisti di runtime. Ecco perché la libreria standard, poiché la versione C++ 11 ha aggiunto puntatori intelligenti che cancellano automaticamente la memoria a cui puntano. std::unique_ptr è un tipo di puntatori intelligenti, che consente solo a se stesso di puntare a un dato oggetto. Notare che l’allocazione viene ancora eseguita utilizzando l’operatore new e dopo che il puntatore è stato utilizzato possiamo uscire dal programma senza chiamare 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;
}

Produzione:

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

Usa la funzione malloc e realloc / reallocarray per allocare la memoria dinamica

D’altra parte, il codice C++ può chiamare la funzione allocatore originale in stile C - malloc, che è un modo abbastanza arcaico di manipolazione dinamica della memoria per i moderni standard C++. Non è il modo consigliato per allocare gli oggetti nell’heap, ma il lato positivo è che malloc fornisce funzionalità più flessibili.

malloc viene chiamato con un singolo argomento che specifica l’oggetto sizeof e restituisce void* che dovrebbe essere convertito nel tipo corrispondente in C++. L’unico vantaggio della memoria allocata malloc è che può essere espansa / ridotta dalla funzione realloc o reallocarray. La funzione realloc prende il puntatore all’oggetto e la nuova dimensione come argomenti, mentre reallocarray prende il puntatore, il numero di elementi e la dimensione di ogni elemento. Si noti che se la memoria dell’oggetto viene espansa, i vecchi valori memorizzati rimangono intatti e gli elementi appena aggiunti non vengono inizializzati. Pertanto, il seguente esempio stampa gli elementi espansi arr3 solo a scopo dimostrativo, e non dovrebbe essere il caso nel programma del mondo reale.

#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;
}

Produzione:

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;
Autore: 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

Articolo correlato - C++ Memory