Alocare Dinamică în C++
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ă
ListNodecare conține un număr naturalinfoși 2 pointeri către alteListNodeuri 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
ListNodesă 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ă
TreeNodecare 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 *fathercare 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.