alocarea dinamic Ă a memoriei

35
ALOCAREA DINAMIC ALOCAREA DINAMIC Ă A Ă A MEMORIEI MEMORIEI Prof. ADINA-ELENA PIŢIGOI

Upload: thai

Post on 14-Feb-2016

39 views

Category:

Documents


1 download

DESCRIPTION

ALOCAREA DINAMIC Ă A MEMORIEI. Prof. ADINA-ELENA P IŢIGOI. GENERALITĂŢI. Definiţii Prin pointer înţelegem adresa unei variabile, iar printr-o variabila de tip pointer vom înţelege o variabilă care poate reţine adresele altor variabile - PowerPoint PPT Presentation

TRANSCRIPT

Page 1: ALOCAREA DINAMIC Ă A MEMORIEI

ALOCAREA DINAMICALOCAREA DINAMICĂ A Ă A MEMORIEIMEMORIEI

Prof. ADINA-ELENA PIŢIGOI

Page 2: ALOCAREA DINAMIC Ă A MEMORIEI

GENERALITĂŢIGENERALITĂŢIDefiniţii• Prin pointer înţelegem adresa unei variabile, iar

printr-o variabila de tip pointer vom înţelege o variabilă care poate reţine adresele altor variabile

• Prin alocarea dinamică a memoriei vom înţelege alocarea unor variabile în Heap, alocare care se face în timpul executării programului şi nu de la început, aşa cum am fost obişnuiţi până acum. Mecanismul alocării dinamice a memoriei necesită utilizarea pointerilor şi evident, a variabilelor de tip pointer.

Page 3: ALOCAREA DINAMIC Ă A MEMORIEI

Avantajele alocării dinamice Avantajele alocării dinamice sunt:sunt:

Programul va utiliza atâta memorie cât are nevoie. Nu întotdeauna se poate cunoaşte, de la început, de câtă memorie are nevoie, aceasta se decide în timpul executării, în funcţie de datele de intrare.

Dacă o variabilă nu mai este necesară, există posibilitatea să eliberăm memoria ocupată de aceasta. O astfel de abordare conduce la micşorarea substanţială a necesarului de memorie a unui program.

Page 4: ALOCAREA DINAMIC Ă A MEMORIEI

Variabile de tip pointerVariabile de tip pointer

Definiţii• Numărul de ordine al unui octet se

numeşte adresa lui • Adresa primului octet al variabilei se

numeşte adresa variabilei.

Page 5: ALOCAREA DINAMIC Ă A MEMORIEI

ObservaţiiObservaţii• Nu trebuie confundată adresa unei

variabile cu valoarea pe care aceasta o memorează!

• Pointerul este adresa unei variabile.Memorarea adreselor variabilelor se face cu

ajutorul variabilelor de tip pointer.Variabilele de tip pointer se caracterizează

prin faptul că valorile pe care le pot memora sunt adrese ale altor variabile.

Page 6: ALOCAREA DINAMIC Ă A MEMORIEI

Limbajul C++ face distincţie între natura adreselor care pot fi memorate. Astfel, există adrese ale variabilelor de tip int, adrese ale variabilelor de tip float, adrese ale variabilelor de tip char, etc. Din acest motiv şi tipul variabilelor de tip pointer este diferit.

Page 7: ALOCAREA DINAMIC Ă A MEMORIEI

Declararea tipului unei variabile Declararea tipului unei variabile de tip pointer:de tip pointer:

tip *nume;• Variabile de tip pointer către variabile de tip int.

Variabilele adr1 şi adr2 pot reţine adrese ale variabilelor de tip int.

int *adr1, *adr2;• Variabile de tip pointer către variabile de tip

float. Variabila adresa poate reţine adrese ale variabilelor de tip float:

float* adresa;

Page 8: ALOCAREA DINAMIC Ă A MEMORIEI

Declararea tipului unei variabile Declararea tipului unei variabile de tip pointer:de tip pointer:

Variabile de tip pointer către variabile de tip elev, care la rândul lor sunt de tip struct. Variabilele a şi b, pot reţine adrese ale variabilelor de tipul elev.

struct elev{ char nume[20], prenume[20] ; float nota_mate, nota_info; int varsta;};

elev *a,*b;

Page 9: ALOCAREA DINAMIC Ă A MEMORIEI

ObservaţiiObservaţii• Caracterul "*" poate fi aşezat în mai multe feluri,

după cum se observă:int* adr1; int * adr1; int *adr1;

• Pentru a declara mai multe variabile de acest tip, caracterul "*" se trece de fiecare dată:

int *adr1, *adr2, *adr3;• Declaraţia

int* adr1, adr2;are semnificaţia că adr1 este de tip pointer către

int, şi adr2 este de tip int.

Page 10: ALOCAREA DINAMIC Ă A MEMORIEI

Adresa unei variabile se obţine cu ajutorul operatorului de referenţiere "&", care trebuie să preceadă numele variabilei:

&Nume_variabilă;

Ex:adr1=&număr;

- variabilei adr1 i se atribuie adresa variabilei număr.

Page 11: ALOCAREA DINAMIC Ă A MEMORIEI

Fiind dată o variabilă de tip pointer către variabile de un anume tip, care memorează o adresă a unei variabile de acel tip, pentru a obţine conţinutul variabilei a cărei adresă este memorată, se utilizează operatorul unar "*", numit şi operator de dereferenţiere.

Page 12: ALOCAREA DINAMIC Ă A MEMORIEI

int a=7, *adr=&a; cout<<*adr;

Variabila a este iniţializată cu 7, iar variabila adr este initializată cu adresa lui a. Secvenţa afişează conţinutul variabilei a (7), pornind de la adresa ei, reţinută de adr.

Page 13: ALOCAREA DINAMIC Ă A MEMORIEI

Variabila a de tip elev este iniţializată, iar variabila adra, de tip pointer către variabile de tip elev este iniţializată cu adresa variabilei a.

…struct elev {char nume[20], prenume[20];};…elev a, *adra=&a;strcpy(a. nume,"Bojian") ;strcpy(a.prenume,

"Andronache");cout<< (*adra) .nume«" “;cout<< (*adra) .prenume<<endl;

Page 14: ALOCAREA DINAMIC Ă A MEMORIEI

Evaluarea expresiei Evaluarea expresiei (*adra).nume(*adra).nume

• Operatorul "." - numit operator de selecţie, are prioritatea 1, deci maximă.

• Operatorul "*" - unar, numit şi operator de dereferenţiere, are prioritatea 2, mai mică. Prin urmare, în absenţa parantezelor rotunde, se încearcă mai întâi evaluarea expresiei "adra.nume", expresie care n-are sens! Parantezele schimbă ordinea de evaluare, se evalueaza mai întâi "*adra", expresie care are sens.

Page 15: ALOCAREA DINAMIC Ă A MEMORIEI

ObservaţieObservaţie

În loc să folosim trei operatori, se poate utiliza unul singur, operatorul de selectie indirecta: "->".

Acesta accesează un câmp al unei structuri pornind de la un pointer (adresă) către acea structură. El are prioritatea maximă.

Tipărirea se face:cout<<adra->nume<<" "<<adra->prenume;

Page 16: ALOCAREA DINAMIC Ă A MEMORIEI

Între variabile de tip pointer sunt permise atribuiri doar în cazul în care au acelaşi tip pointer (reţin adrese către acelaşi tip de variabile).

Ex:int *adr1, *adr2;float *adr3;... // initializari

Atribuirea "adr1=adr2" este corectă, iar atribuirea "adr3=adr2" nu este corectă. În acest caz, se utilizează operatorul de conversie explicită. "adr3= (float*) adr2" este corectă.

Page 17: ALOCAREA DINAMIC Ă A MEMORIEI

Alocarea dinamică a memorieiAlocarea dinamică a memoriei

Operatorul new alocă spaţiu în heap pentru o variabilă dinamică. După alocare, adresa variabilei se atribuie lui p, unde p este o variabilă de tip pointer către tip:

p=new tip

Page 18: ALOCAREA DINAMIC Ă A MEMORIEI

ObservaţiiObservaţii• Numărul de octeţi alocaţi în heap este

egal cu numărul de octeţi ocupat de o variabilă de tipul respectiv.

• Durata de viaţă a unei variabile alocate în heap este până la eliberarea spaţiului ocupat (cu delete) sau până la sfârşitul executării programului.

Page 19: ALOCAREA DINAMIC Ă A MEMORIEI

• Operatorul delete eliberează spaţiul rezervat pentru variabila a cărei adresă este reţinută în p. După eliberare, conţinutul variabilei p este nedefinit.

delete p;

Page 20: ALOCAREA DINAMIC Ă A MEMORIEI

Variabile de tip pointer către Variabile de tip pointer către variabile de tip intvariabile de tip int

int* adr1;adr1=new int; // aloc spaţiu în HEAP

pentru o variabilă de tip int *adr1=7; //variabila alocată reţine 7 cout<<*adr1; // tipăresc conţinutul

variabilei delete adr1; // eliberez spaţiul

Page 21: ALOCAREA DINAMIC Ă A MEMORIEI

Variabile de tip pointer către Variabile de tip pointer către variabile de tip floatvariabile de tip float

float* adresa; // sau float* adresa=new

float; adresa=new float; *adresa=7.65; cout<<*adresa;

Page 22: ALOCAREA DINAMIC Ă A MEMORIEI

Variabile de tip Variabile de tip pointer pointer către către variabile de tip variabile de tip inreginreg, care la , care la rândul lor, sunt de tip rândul lor, sunt de tip structstruct

#include <iostream.h> struct inreg

{ char nume[20], prenume[20]; int varsta;

}; main(){ inreg* adr; adr=new inreg;cin>>adr->nume>>adr->prenume>>adr->varsta;cout < < adr->nume<<endl<<adr->prenume< <endl;cout<<adr->varsta;}

Page 23: ALOCAREA DINAMIC Ă A MEMORIEI

Mecanismul alocării dinamiceMecanismul alocării dinamiceUn tablou p-dimensional se declară astfel:

tip nume [n1] [n2] . . . [np]Ex:float a[7][4][2]; - am declarat un tablou cu

3 dimensiuni, unde tipul de bază este float.

long b[9] [7] [8] [5]; - am declarat un tablou cu 4 dimensiuni, unde tipul de bază este long.

Page 24: ALOCAREA DINAMIC Ă A MEMORIEI

Numele tabloului p dimensional de mai sus este pointer constant către un tablou p-1 dimensional de forma [n2]... [np], care are componentele de baza de acelaşi tip cu cele ale tabloului.

a este pointer constant către tablouri cu [4] [2] componente de tip float;

b este pointer constant către tablouri cu [7] [8] [5] componente de tip long.

float a[7][4][2]; long b[9] [7] [8] [5];

tip nume [n1] [n2] . . . [np]

Page 25: ALOCAREA DINAMIC Ă A MEMORIEI

Un pointer către un tablou k dimensional cu [l1] [l2] …[lk] componente de un anumit tip se declară astfel:

tip (*nume) [l2] …[lk] Ex:- variabila de tip pointer, numită p, care

poate reţine pe a, se declară:float (*p)[4] [2];

- variabila de tip pointer, numită q, care poate reţine pe b, se declară:

long (*q) [7] [8] [5];float a[7][4][2]; long b[9] [7] [8] [5];

Page 26: ALOCAREA DINAMIC Ă A MEMORIEI

Operatorul de tip [] are cea mai mare prioritate (mai mare decât operatorul "*"). Declaraţia

float *p[7][8][5];este interpretată ca masiv cu [7] [8] [5] componente de tip float*.

Deci este masiv cu componente de tip pointer şi nu pointer către masive.

Page 27: ALOCAREA DINAMIC Ă A MEMORIEI

Intrucât numele unui masiv p dimensional este pointer către un masiv p-1 dimensional, pentru a aloca dinamic un masiv se va utiliza un pointer către masive p-1 dimensionale (ultimele p-1 dimensiuni).

Page 28: ALOCAREA DINAMIC Ă A MEMORIEI

Alocăm în heap un vector cu 4 componente de tip int. Numele unui astfel de vector are tipul int* (pointer către int). Prin urmare, variabila a are tipul int*. După alocare, ea va conţine adresa primului element al vectorului din heap. Din acest moment, pornind de la pointer (reţinut în a) vectorul se adresează exact cum suntem obişnuiţi.

int *a =new int[4]; a[3]=2;

Observaţi modul în care a fost trecut tipul în dreapta operatorului new. Practic, declararea tipului se face întocmai ca declaraţia masivului, însă numele a fost eliminat.

Page 29: ALOCAREA DINAMIC Ă A MEMORIEI

• Declaram în heap o matrice (masiv bidimensional) cu 3 linii şi 5coloane, cu elemente de tip double:

double (*a) [5] = new double [3] [5]; a[1] [2]=7.8;

Page 30: ALOCAREA DINAMIC Ă A MEMORIEI

În cazul masivelor, la eliberarea În cazul masivelor, la eliberarea memoriei (cu delete) trebuie ţinut memoriei (cu delete) trebuie ţinut cont de tipul pointerului.cont de tipul pointerului. Fie vectorul alocat în heap,

int *a =new int [4];Daca încercăm dezalocarea sa prin:

delete a;îi dezalocăm prima componentă, pentru că

pointerul este de tip int*.Dezalocarea se poate face prin

delete [4] a;eliberam spaţiul pentru toate componentele (în

acest caz avem 4).

Page 31: ALOCAREA DINAMIC Ă A MEMORIEI

Fie matricea alocată în heap:

double (*a)[5]=new double [3] [5];

Eliberarea spaţiului ocupat de ea se face prin

delete [3] a;

Page 32: ALOCAREA DINAMIC Ă A MEMORIEI

Citirea şi afişarea unei matrice Citirea şi afişarea unei matrice alocate în HEAPalocate în HEAP

#include <iostream.h> main(){ int m,n,i,j,(*adr)[10]; adr=new int[10][10]; cout«"m="; cin>>m; cout<<"n="; cin>>n; for(i=0;i<m;i++)

for (j=0;j<n;j++) cin>>adr[i][j]; for(i=0;i<m;i++)

{ for (j=0;j<n; j++) cout<<adr[i][j]<<" ";cout<<endl;}

}

Page 33: ALOCAREA DINAMIC Ă A MEMORIEI

Funcţiile nu pot întoarce masive.O funcţie poate întoarce un pointer către orice tip

(void*). Unei variabile de tipul void* i se poate atribui orice

tip de pointer, dar atribuirea inversa se poate face doar prin utilizarea operatorului de conversie explicită.

Programul următor citeşte două matrice şi afişează suma lor. Matricele sunt alocate în heap.

Page 34: ALOCAREA DINAMIC Ă A MEMORIEI

#include <iostream.h>void* Cit_Mat(int m, int n)

{ int i,j, (*adr1)[10]=new int[10][10]; for(i=0;i<m;i++)for (j= 0;j<n;j++) cin>>adrl[i] [j] ; return adr1;}

void Tip_Mat( int m,int n,int(*adr1)[10]) { int i,j; for(i=0;i<m;i++)

{ for (j=0;j<n;j++) cout<<adr1 [i] [j] <<" "; cout<<endl; }

}

Page 35: ALOCAREA DINAMIC Ă A MEMORIEI

void* Suma_Mat( int m, int n,int(*adr1)[10],int(*adr2)[10]) { int i,j,(*adr)[10]=new int[10][10]; for (i=0;i<m;i++) for (j=0;j<n;j++)

adr[i][j]=adr1[i][j]+adr2[i][j]; return adr;

}main(){ int m,n,i,j,(*adr)[10],(*adr1)[10],(*adr2)[10];

cout<<"m="; cin>>m; cout«"n="; cin>>n; adr1=(int(*)[10]) Cit_Mat(m,n); adr2=(int(*)[10]) Cit_Mat(m,n); adr=(int(*)[10]) Suma_Mat(m,n,adr1,adr2); Tip_Mat(m,n,adr);

}