Alocare Dinamică, C++ style
malloc
și free
își fac treaba foarte bine, dar odată cu apariția claselor a apărut nevoia pentru un mod de a aloca dinamic memorie prin care se apelează constructorul.
new
new T
alocă memorie pentru un obiect de tipul T
, apelează constructorul și întoarce un pointer către acesta. Se pot specifica și parametri pentru constructor.
Pentru a aloca un tip de date de bază:
uint32_t *ptr = new uint32_t;
Pentru a aloca un obiect cu alt constructor decât cel implicit:
Vector2 *vec = new Vector2(1.f, 3.f);
unde Vector2
are definiția:
class Vector2 {
public:
float x, y;
Vector2() {
x = 0.f;
y = 0.f;
}
Vector2(float x, float y) {
this->x = x;
this->y = y;
}
};
delete
delete ptr
apelează destructorul și eliberează memoria alocată pentru obiectul aflat la adresa ținută în ptr
.
new[]
new T[len]
alocă memorie contiguă pentru len
obiecte de tipul T
și apelează constructorul implicit pentru fiecare în parte, dacă T
este clasă.
Pentru a aloca un array de len
elemente cu tip de date de bază:
uint32_t *u = new uint32_t[len]; // Neinițializate
uint32_t *v = new uint32_t[len](); // Inițializate cu 0
Pentru a aloca un array de len
obiecte de tip T
:
T *v = new T[len]; // Constructorul cu 0 parametri
delete[]
delete[] v
apelează destructorul pe fiecare element din arrayul care începe la adresa v
și eliberează memoria alocată.
Atenție: delete v
în loc de delete[] v
șterge doar primul element dacă este apelat pe un array. Pointerul la array este în același timp pointerul la primul element.
Exerciții
- Creați o clasă
ListNode
care conține un număr naturalinfo
și 2 pointeri către alteListNode
uri inițialize penullptr
. - Adăugați un constructor care ia ca argument un singur
uint32_t info
. - Adăugați o metodă
ListNode *insertAfter(const uint32_t &info)
care inserează un nou nod după cel curent, păstrează integritatea listei dublu înlănțuite și întoarce adresa noului nod. - Adăugați o metodă
void printList()
care afișează lista dublu înlănțuită începând cu nodul curent. - Adăugați o metodă
ListNode *erase()
care elimină din lista dublu înlănțuită nodul curent, păstrează integritatea listei și întoarce adresa următorului nod din listă. - Adăugați o metodă și variabile membru utile astfel încât fiecare nod din
ListNode
să rețină și divizorii primi ai număruluiinfo
, fără a consuma inutil memorie și fără a crea memory leakuri. - Creați o clasă
TreeNode
care conține un număr naturalinfo
și un array alocat dinamic de pointeri către fiii nodului. - Adăugați un constructor care ia ca argument un singur
uint32_t info
. - Adăugați un constructor care ia ca argument un
uint32_t info
și unTreeNode *father
care creează un nod nou și îl adaugă ca fiu al noduluifather
, dacă acesta este diferit denullptr
. - Adăugați o metodă
TreeNode *addChild(TreeNode *child)
care adaugă un nod deja existent ca fiu al nodului curent. - Adăugați o metodă
TreeNode *createChild(const uint32_t &info)
care creează un nod nou cu informațiainfo
și o adaugă ca fiu al nodului curent. - Testați și asigurați-vă că nu aveți memory leakuri.