Verwendung von malloc vs new-Allokatoren in C++
-
Verwenden Sie den
new
-Operator, um dynamischen Speicher in C++ zu allozieren -
Mit dem
new
-Operator undstd::unique_ptr
dynamischen Speicher in C++ allozieren -
Verwenden Sie die Funktion
malloc
undrealloc
/reallocarray
, um dynamischen Speicher zu allozieren
In diesem Artikel werden verschiedene Methoden der Verwendung von malloc
vs. new
-Allokatoren in C++ erläutert.
Verwenden Sie den new
-Operator, um dynamischen Speicher in C++ zu allozieren
new
ist die bevorzugte Schnittstelle, um dynamischen Speicher in C++ direkt zu verwalten. Sie konstruiert ein Objekt des angegebenen Typs und gibt den Zeiger auf dieses Objekt zurück. Objekte, die mit dem new
-Operator alloziert werden, sind standardmäßig initialisiert, was bedeutet, dass Objekte vom eingebauten und zusammengesetzten Typ Garbage-Werte haben, die vor der Verwendung initialisiert werden müssen.
Beachten Sie, dass new
mit verschiedenen Notationen aufgerufen werden kann, um verschiedenen Bedürfnissen gerecht zu werden, aber im folgenden Beispiel weisen wir das Array int
der Größe 10
zu. Daher zeigt der zurückgegebene Zeiger, der in der Variablen arr1
gespeichert ist, auf den Speicherabschnitt, der 40
Bytes groß ist. Die Funktion initPrintIntVector
ist nur implementiert, um ein praktisches Kodierbeispiel besser zu demonstrieren. Da wir einen sogenannten nackten Zeiger verwenden, ist es wichtig, den allozierten Speicher mit dem delete
-Operator freizugeben, bevor das Programm beendet wird. Beachten Sie aber, dass Klammern nach dem delete
auch notwendig sind, um jede Stelle im Array wieder freizugeben.
#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;
}
Ausgabe (*zufällig):
8; 380; 519; 536; 408; 666; 382; 244; 448; 165;
Mit dem new
-Operator und std::unique_ptr
dynamischen Speicher in C++ allozieren
Auch wenn der new
-Operator ein gutes Werkzeug für die dynamische Speicherallokation zu sein scheint, kann er in großen Codebases mit intensiven Speichermanipulationen recht fehleranfällig werden. Die Deallokation der Speicherressourcen zum richtigen Zeitpunkt ist nämlich ein ziemlich schwer zu bewältigendes Problem, das meist zu Speicherlecks oder unerwarteten Laufzeitfehlern führt. Aus diesem Grund hat die Standardbibliothek seit der C++ 11-Version intelligente Zeiger hinzugefügt, die den Speicher, auf den sie zeigen, automatisch löschen. std::unique_ptr
ist ein Typ von intelligenten Zeigern, der nur sich selbst erlaubt, auf das gegebene Objekt zu zeigen. Beachten Sie, dass die Zuweisung immer noch mit dem new
-Operator erfolgt, und nachdem der Zeiger verwendet wurde, können wir das Programm ohne Aufruf von delete
verlassen.
#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;
}
Ausgabe:
985; 885; 622; 899; 616; 882; 117; 121; 354; 918;
Verwenden Sie die Funktion malloc
und realloc
/reallocarray
, um dynamischen Speicher zu allozieren
Auf der anderen Seite kann der C++-Code die ursprüngliche C-artige Allokationsfunktion - malloc
- aufrufen, die für moderne C++-Standards eine ziemlich archaische Art der dynamischen Speichermanipulation ist. Es ist nicht die empfohlene Art, Objekte auf dem Heap zu allozieren, aber auf der Plusseite bietet malloc
eine flexiblere Funktionalität.
malloc
wird mit einem einzigen Argument aufgerufen, das das sizeof
-Objekt angibt, und es gibt ein void*
zurück, das in C++ auf den entsprechenden Typ gecastet werden sollte. Der einzige Vorteil des mit malloc
allozierten Speichers ist, dass er mit der Funktion realloc
oder reallocarray
erweitert/geschrumpft werden kann. Die Funktion realloc
nimmt den Zeiger auf das Objekt und die neue Größe als Argumente, während reallocarray
den Zeiger, die Anzahl der Elemente und die Größe der einzelnen Elemente nimmt. Beachten Sie, dass, wenn der Objektspeicher erweitert wird, die alten gespeicherten Werte erhalten bleiben und neu hinzugefügte Elemente nicht initialisiert werden. Daher gibt das folgende Beispiel die erweiterten arr3
-Elemente nur zu Demonstrationszwecken aus, was im realen Programm nicht der Fall sein sollte.
#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;
}
Ausgabe:
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