Usa malloc rispetto ai new allocatori in C++
-
Usa il
new
operatore per allocare la memoria dinamica in C++ -
Usa il
new
operatore estd::unique_ptr
per allocare la memoria dinamica in C++ -
Usa la funzione
malloc
erealloc
/reallocarray
per allocare la memoria dinamica
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;
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