Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
POO - Curs Doc-1.doc
Скачиваний:
0
Добавлен:
01.07.2025
Размер:
868.86 Кб
Скачать

§11. Dirijarea dinamică a memoriei

Toate posibilităţile de dirijare dinamică a memoriei existente în limbajul C sunt valabile şi în limbajul C++. Este vorba de funcţiile malloc(), calloc(), realloc(), free(). Iată prototipurile acestor funcţii:

void *malloc(size_t dim_loc);

void *calloc(size_t num_el, size_t dim_el);

void *realloc(void *adr_loc, size_t dim_nou);

void free(void *adr_loc);

Limbajul C++ mai are şi posibilităţi proprii încorporate în limbaj sub forma de operatori care permit, de asemenea, dirijarea dinamică a memoriei.

Pentru alocare de memorie este utilizat operatorul new. Modul de utilizare a operatorului new poate fi descris astfel:

tip *adr_locatie;

. . .

adr_locatie=new tip; //aloca memorie de tipul dat

unde adr_locatie este un identificator care reprezintă numele pointerului în care este plasată adresa locaţiei de memorie alocată, utilizând operatorul new, iar tip determină la ce tip de date va fi atribuită locaţia dată de memorie. Dacă operatorul new se execută cu succes, valoarea din pointerul adr_locatie va fi adresa locaţiei de memorie alocată, în caz contrar, în pointer va fi plasată o valoare nulă, care poate fi exprimată prin constanta simbolică NULL. Iată un exemplu:

int *adri;

adri=new int;

În procesul alocării de memorie în locaţia dată poate fi plasată şi o valoare iniţială. Modul de aplicare a operatorului new se schimbă puţin după cum urmează:

tip *adr_locatie;

. . .

adr_locatie=new tip(val); // alocare cu initializare

De exemplu:

float *Pi;

Pi = new float(3.14);

ceea ce este echivalent cu:

float *Pi;

Pi= new float;

*Pi = 3.14;

Ideile expuse anterior sunt aplicabile integral tipurilor predefinite de date. În cazul tipurilor abstracte de date (clase) definite de programator trebuie de ţinut cont că la crearea oricărui obiect participă şi constructorul clasei. De aceea în continuare este propusă o descriere care generalizează descrierile anterioare, obţinând o descriere aplicabilă în contextul claselor:

nume_cl *adr_obiect;

adr_obiect = new nume_cl[(lista_par_reali)];

unde lista_par_reali reprezintă parametrii reali transmişi constructorului pentru a putea îndeplini acţiunile de creare a obiectului şi din câte se vede este un element opţional. Lista parametrilor reali poate lipsi atunci când clasa nu are constructor, sau are constructor fără parametri, sau constructorul poate fi redus la un constructor fără parametri. De exemplu, luând ca bază clasa punct, poate fi adus următorul exemplu:

punct *pp;

pp=new punct(112,37); //adresa obiect in pointer pp

pp->afisare();

Pentru a elibera spaţiul alocat pentru o variabilă de anumit tip, este utilizat operatorul delete. Forma de aplicare a operatorului este următoarea:

delete adr_locatie;

unde variabila adr_locatie conţine adresa locaţiei de memorie alocată cu ajutorul operatorului new. Dacă este eliberat spaţiul alocat pentru un obiect, va fi apelat mai întâi destructorul clasei respective. Pentru a elibera memoria alocată, în exemplul referitor la clasa punct va fi scris astfel:

delete pp;

În afară de posibilitatea de alocare a spaţiului pentru o singură variabilă de anumit tip, există posibilitatea de a aloca spaţiu de memorie pentru un tablou de elemente de anumit tip. În acest scop, va fi utilizată următoarea descriere:

tip *adr_locatie;

. . .

adr_locatie = new tip[dim]; //alocare memorie tablou

unde adr_locatie va conţine adresa spaţiului alocat tabloului de elemente. Ca exemplu va fi alocat spaţiu pentru 10 elemente de tip double:

double *adrd;

adrd = new double[10];

Vom menţiona faptul că la alocarea de memorie pentru tablouri nu poate fi efectuată concomitent şi iniţializarea elementelor, ca în cazul unei singure variabile. De acest fapt trebuie de ţinut cont mai ales la crearea tablourilor de obiecte, fiindcă crearea unui obiect apelând un constructor cu un anumit set de parametri reali ar însemna o “iniţializare” a obiectului. Şi fiindcă la crearea tablourilor nu este posibilă apelarea unui constructor cu parametri, clasa respectivă neapărat va trebui să conţină un constructor fără parametri sau un constructor care se reduce la un constructor fără parametri. Pentru clasa punct este posibilă crearea unui tablou de 20 obiecte:

punct *tabp;

tabp = new punct[20];

Eliberarea spaţiului de memorie ocupat de un tablou de elemente se realizează cu ajutorul operatorului delete[] scriind astfel:

delete[] adr_locatie;

unde adr_locatie conţine adresa tabloului de elemente.

În cazul tipurilor de date simple, rezultatul acţiunii operatorului delete şi al operatorului delete[] poate fi acelaşi, însă în cazul tablourilor de obiecte sunt cazuri când rezultatul acţiunilor lor nu sunt echivalente. La execuţia operatorului delete[] pentru un tablou de obiecte va fi apelat destructorul pentru fiecare element al tabloului, ceea ce va genera o eliberare corectă a memoriei ocupate. La execuţia operatorului delete pentru un tablou de obiecte va fi apelat destructorul doar pentru primul element al tabloului şi deci poate fi generată o eliberare incompletă a resurselor folosite de obiecte.

Operatorii new şi delete au o serie de avantaje în comparaţie cu funcţiile de dirijare dinamică a memoriei:

  1. operatorii new şi delete pot fi supraîncărcaţi schimbând acţiunea lor în cadrul unor clase;

  2. în procesul de alocare a memoriei nu sunt necesare anumite conversii ale tipurilor de date;

  3. nu sunt necesare anumite calcule preliminare pentru a determina dimensiunea fragmentului de memorie.

Iată cum este alocată memoria pentru un tablou de 10 elemente de tip int cu ajutorul funcţiei malloc()

int *ai;

ai = (int *)malloc(sizeof(int)*10);

În continuare, pentru comparaţie, este efectuat acelaşi lucru utilizând operatorul new:

int *ai;

ai = new int[10];

Vom remarca faptul că dacă se folosesc funcţiile malloc(), calloc(), realloc() pentru alocare de memorie, atunci se utilizează doar funcţia free() pentru eliberarea memoriei, iar dacă este folosit operatorul new pentru alocare, atunci eliberarea memoriei se face doar cu operatorul delete. Nu se permite combinarea de diferite mecanisme la nivel de alocare şi eliberare a memoriei.

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]