Puntatori
Dichiarazione di variabili puntatore
Assegnazione: operatore unitario prefisso &
Dereferenziazione: operatore unitario prefisso *
Relazione tra puntatori ed array
Allocazione dinamica della memoria (scalari)
Allocazione dinamica della memoria (array)
Allocazione dinamica della memoria (matrici)
Puntatori
Dato un tipo di variabile, ad es. double, il tipo double
* si chiama puntatore (a double, nell'esempio), ed e' una variabile
che assume, come valore, l'indirizzo di memoria in cui e' contenuta una
variabile del tipo corrispondente (double, nell'esempio), cioe' e' una
variabile il cui valore punta ad una variabile.
Nota: per definire una variabile puntatore bisogna
definire il tipo di variabile a cui esso punta; un puntatore a double
ed un puntatore ad int, ad esempio, sono variabili di tipo differente,
come double e' un tipo differente da int.
Dichiarazione di variabili puntatori
Le variabili puntatore si dichiarano utilizzando il simbolo *, nel
seguente modo:
double *dp;
// puntatore a double
unsigned short int *usip;
// puntatore a unsigned short int
string *sp;
// puntatore a variabile di tipo string
Assegnazione: operatore unitario
prefisso &
L'operatore unitario & posto davanti al nome di una variabile
serve ad indicare l'indirizzo occupato dalla variabile in questione. In
questo modo e' possibile assegnare un valore ai puntatori:
double d;
double * pd = &d;
// il puntatore a double pd assume come valore l'indirizzo della variabile
d
E' possibile assegnare ad un puntatore il valore di un altro puntatore:
int i;
int * ip1 = &i;
// il puntatore ip1 punta alla variabile i
int * ip2 = ip1;
// il puntatore ip2 punta anch'esso alla variabile i
Quando si dichiara un puntatore senza contemporaneamente inizializzare il suo valore, e' opportuno inizializzarlo ad un valore invalido, che per i puntatori si chiama NULL:
char * cp = NULL;
Dereferenziazione: operatore
unitario prefisso *
L'accesso ad una variabile tramite un puntatore si chiama dereferenziazione.
Per fare cio' si utilizza l'operatore unitario prefisso *:
double d;
double * dp = &d;
// dp punta alla double d
*dp = 12.0;
// questo e' equivalente a scrivere d = 12.0, ma uso il puntatore
cout << *d << endl;
// stampo su terminale il valore di d, usando il puntatore
a tutti gli effetti, *dp equivale a scrivere d
Relazione tra puntatore ed array
Il nome della variabile array (senza le []) puo' essere trattato come
un puntatore al primo elemento dell'array.
int v[3] = {2, 4, 6};
cout << *v << endl;
// v punta al primo elemento, quindi *v e' il primo elemento
In modo simmetrico, un puntatore a cui sia assegnato l'indirizzo del primo elemento di un array, puo' essere utilizzato come una variabile array:
int *p = NULL;
p = v;
// equivalente a p = & v[0]; (indirizzo del primo elemento)
p[2] = 3.0;
// accesso al terzo elemento dell'array tramite un puntatore
Allocazione dinamica della memoria
(scalari)
Per allocare dinamicamente la memoria, per contenere ad esempio variabili
o array non dichiarati,
si utilizza l'istruzione new. Questa istruzione assegna ad un
puntatore l'indirizzo della memoria allocata.
Assieme a new, va specificato il tipo di oggetto che si vuole allocare.
double * p = NULL;
p = new double;
// p assume il valore della zona di memoria allocata per una double
*p = 23.4;
// assegno un valore alla zona di memoria allocata
Per deallocare la memoria allocata dinamicamente si usa l'istruzione delete:
delete p; // libero la memoria allocata precedentemente con new
Allocazione dinamica della memoria
(array)
Per allocare dinamicamente un array, va utilizzata l'istruzione new
specificando il tipo e la dimensione dell'array. L'istruzione assegna ad
un puntatore l'indirizzo del primo elemento allocato. La dimensione dell'array
puo' essere una variabile, e anche una operazione algebrica tra variabili.
int n=3, m=4;
double * p = new double[n+m];
// alloco un array di n+m elementi
Per deallocare un array, si usa l'istruzione delete[]:
delete[] p;
Nota: l'istruzione delete p dealloca solo la memoria occupata dal primo elemento dell'array!
Allocazione dinamica della memoria
(matrici)
L'allocazione dinamica di una matrice nXm si attua in due parti: prima
si alloca un array di n puntatori, e per ciascuno di questi si alloca un
array di m variabili (il contenuto di ciascuna riga della matrice):
int nrow, ncol;
double **matrix;
matrix = new double*[nrow];
// alloco l'array di puntatori a double
for(int i=0; i<nrow; ++i)
matrix[i] = new double[ncol];
// per ogni riga alloco l'array di double per gli elementi della riga
La deallocazione di una matrice va fatta secondo l'ordine inverso rispetto alla allocazione:
for(int i=0; i<nrow; ++i)
delete[] matrix[i];
delete[] matrix