Dynamiczna alokacja pamięci w C/C++ oznacza ręczne przydzielanie pamięci przez programistę. Pamięć przydzielana dynamicznie jest przydzielana Sterta, a zmienne niestatyczne i lokalne otrzymują przydzieloną pamięć Stos (Odnosić się do Programy C dotyczące układu pamięci dla szczegółów).
Co to są aplikacje?
- Jednym z zastosowań pamięci alokowanej dynamicznie jest alokacja pamięci o zmiennym rozmiarze, co nie jest możliwe w przypadku pamięci alokowanej przez kompilator, z wyjątkiem tablice o zmiennej długości .
- Najważniejszym zastosowaniem jest elastyczność zapewniana programistom. Możemy swobodnie alokować i zwalniać pamięć, kiedy jej potrzebujemy i kiedy już jej nie potrzebujemy. Jest wiele przypadków, w których taka elastyczność jest pomocna. Przykładami takich przypadków są Drzewo itp.
Czym różni się od pamięci przydzielonej zwykłym zmiennym?
W przypadku normalnych zmiennych, takich jak int a, char str[10] itp., pamięć jest automatycznie przydzielana i zwalniana. W przypadku pamięci alokowanej dynamicznie, np. int *p = new int[10], obowiązkiem programisty jest zwolnienie pamięci, gdy nie jest ona już potrzebna. Jeśli programista nie zwolni pamięci, powoduje to a wyciek pamięci (pamięć nie jest zwalniana aż do zakończenia programu).
W jaki sposób pamięć jest przydzielana/cofana w C++?
C używa malloc() i calloc() do dynamicznego przydzielania pamięci w czasie wykonywania i używa funkcji free() do zwalniania dynamicznie przydzielonej pamięci. C++ obsługuje te funkcje i ma również dwóch operatorów nowy I usuwać, które wykonują zadanie alokacji i zwalniania pamięci w lepszy i łatwiejszy sposób.
nowego operatora
Nowy operator oznacza żądanie przydziału pamięci w Free Store. Jeśli dostępna jest wystarczająca ilość pamięci, operator new inicjuje pamięć i zwraca adres nowo przydzielonej i zainicjowanej pamięci do zmiennej wskaźnikowej.
Składnia użycia operatora new
Java konwertuje znak na int
pointer-variable = new data-type;>
Tutaj zmienna wskaźnikowa jest wskaźnikiem typu typ-danych. Typ danych może być dowolnym wbudowanym typem danych, w tym tablicą lub dowolnym typem danych zdefiniowanym przez użytkownika, w tym strukturą i klasą.
Przykład:
// 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;>C++
// C++ program to demonstrate how to create dynamic variable // using new #include #include using namespace std; int main() { // pointer to store the address returned by the new int* ptr; // allocating memory for integer ptr = new int; // assigning value using dereference operator *ptr = 10; // printing value and address cout << 'Address: ' << ptr << endl; cout << 'Value: ' << *ptr; return 0; }> Wyjście
Address: 0x162bc20 Value: 10>
Zainicjuj pamięć: Za pomocą operatora new możemy także zainicjować pamięć dla wbudowanych typów danych. W przypadku niestandardowych typów danych wymagany jest konstruktor (z typem danych jako danymi wejściowymi) w celu zainicjowania wartości. Oto przykład inicjalizacji obu typów danych:
pointer-variable = new data-type(value);>
Przykład:
C++ // C++ program to illustrate how to initialize a dynamic // variable with allocation #include #include using namespace std; // Custom data type with constructor to take initial value struct cust { int p; cust(int q) : p(q) { } cust() = default; }; int main() { // creating inbuit data types with initial value int* p = new int(25); float* q = new float(75.25); // Works fine, doesn’t require constructor cust* var1 = new cust; // OR // Works fine, doesn’t require constructor var1 = new cust(); // Notice error if you comment this line cust* var = new cust(25); cout << *p << ' ' << *q << ' ' << var->P; zwróć 0; }> Wyjście
25 75.25 25>
Przydziel blok pamięci: nowy operator jest również używany do alokacji bloku (tablicy) pamięci typu typ danych .
pointer-variable = new data-type[size];>
gdzie size(zmienna) określa liczbę elementów w tablicy.
Przykład:
Zainicjuj listę Pythona
int *p = new int[10]>
Dynamicznie przydziela pamięć dla 10 liczb całkowitych typu int i zwraca wskaźnik do pierwszego elementu sekwencji, do którego przypisano top(wskaźnik). p[0] odnosi się do pierwszego elementu, p[1] odnosi się do drugiego elementu i tak dalej.

Deklaracja normalnej tablicy a użycie nowego
Istnieje różnica pomiędzy deklaracją normalnej tablicy a alokacją bloku pamięci za pomocą new. Najważniejszą różnicą jest to, że kompilator zwalnia normalne tablice (jeśli tablica jest lokalna, alokacja jest usuwana po powrocie lub zakończeniu funkcji). Jednakże dynamicznie przydzielane tablice zawsze tam pozostają, dopóki programista ich nie zwolni lub nie zakończy działania programu.
Co się stanie, jeśli w czasie wykonywania nie będzie dostępnej wystarczającej ilości pamięci?
Jeśli na stercie nie ma wystarczającej ilości pamięci do przydzielenia, nowe żądanie sygnalizuje niepowodzenie, zgłaszając wyjątek typu std::bad_alloc, chyba że z operatorem new zostanie użyte polecenie nothrow, w którym to przypadku zwróci wskaźnik NULL (przewiń do sekcji Wyjątek obsługa nowego operatora w Ten artykuł). Dlatego dobrym pomysłem może być sprawdzenie zmiennej wskaźnikowej utworzonej przez nowy przed użyciem jego programu.
int *p = new(nothrow) int; if (!p) { cout << 'Memory allocation failed
'; }>usuń operatora
Ponieważ za zwolnienie dynamicznie przydzielonej pamięci odpowiada programista, programiści mają do dyspozycji operator usuwania w języku C++.
Składnia:
Java system.out.println
// Release memory pointed by pointer-variable delete pointer-variable;>
Tutaj zmienna wskaźnikowa jest wskaźnikiem wskazującym obiekt danych utworzony przez nowy .
Przykłady:
delete p; delete q;>
Aby zwolnić dynamicznie alokowaną tablicę wskazywaną przez zmienną wskaźnikową, użyj następującej formy usuwać :
// 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 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
'; 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
'; 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; }> Wyjście
Value of p: 29 Value of r: 75.25 Value store in block of memory: 1 2 3 4 5>
Złożoność czasowa: O(n), gdzie n jest danym rozmiarem pamięci.
Powiązane artykuły:
- Quiz na temat nowego i usuwania
- usuń vs za darmo