Un puntatore può puntare a variabili strutturate (di tipo array o record). Esamineremo i seguenti casi:
Tra i casi elencati, il puntatore ad array può utilmente essere sostituito dalla notazione a[i] tipica degli array
Un puntatore ad un array a è una variabile che punta alla prima locazione dell’array (a[0] in C++);
considerando che i successivi elementi dell’array sono allocati in posizioni contigue, esso consente di puntare anche a tutti gli altri elementi dell’array.
T a[dim]; //
a è un array di dim elementi di tipo T
T* p ; //
p è un puntatore a T
p=a;
⇔ p=&a[0];
Un puntatore ad array è dunque di per sé un puntatore al tipo T degli elementi dell’array
const int dim=100;
a è un array di dim elementi di tipo float
float a [dim]; //
//azzeramento di tutti gli elementi di un array di 100 elementi
for
(float* p = a, int i=0;
i<dim; i++, p++)
*p= 0.0;
Se p e q sono due puntatori allo stesso array a, p punta all’elemento a[i] e q all’elemento a[j], la differenza p-q fornisce la “distanza” tra i due elementi.
Un puntatore ad un record è una variabile che punta all’indirizzo di memoria ove il record è allocato;
esso è molto utile nella realizzazione dei tipi dinamici
// Dichiarazioni di un tipo strutturato Ts
struct Ts
{ //
Ts è un tipo strutturato
D1;
.....;
Dn ; };
Ts r ; //
r è variabile di tipo Ts
La funzione di accesso al singolo campo del record è l’operatore punto (.). Per accedere al campo D1 della variabile r la sintassi è: r.D1
// Dichiarazione di variabile di tipo puntatore a Ts
Ts* p;
Ts* p = &r; //
p è una variabile puntatore inizializzata ad r
p può essere ridefinito nel corso del programma
p= &r1; //
ora p punta alla variabile r1 di tipo Ts
Accesso alla singola componente di un record attraverso il puntatore a record:
(*p).Di;
⇔ p->Di;
La gestione delle variabili dinamiche è resa possibile dalla disponibilità dei seguenti meccanismi linguistici:
new
;delete.
T* p = new T;
//alloca memoria sufficiente a
contenere un //
oggetto di tipo T e
restituisce puntatore
T* p1 =new T[n];
//
alloca memoria sufficiente a
contenere n // elementi di tipo T e
restituisce puntatore
In fase di esecuzione, new alloca un’area di memoria sufficiente ad ospitare un valore del tipo T e restituisce il puntatore a tale area.
Il tipo T definisce implicitamente l’ampiezza dell’area di memoria occorrente.
delete p; //
dealloca area puntata da p
delete [] p1;
//dealloca tutto l’array precedentemente allocato
Produce la deallocazione dell’area di memoria puntata dalla variabile p, cioè annulla l’allocazione, rendendo nuovamente disponibile lo spazio di memoria prima occupato.
delete
.Il puntatore p è una variabile automatica, quindi allocata in area stack. Dopo l'istruzione new, p punta ad una locazione nello heap atta a contenere un intero.
Con l’allocazione dinamica di un vettore il puntatore restituito è quello all’indirizzo del primo elemento del vettore, pertanto è di tipo T* se T è il tipo degli elementi del vettore
float* a= new float[n];
Il riferimento agli elementi del vettore viene espresso a mezzo della consueta notazione con indice
a[i] = 10.0 ⇔ *(a+i)=10.0
delete [] a; //
cancella l’intero vettore precedentemente allocato
char* s= new char[n+1];
Un programma che alloca spazio in area heap per una stringa di n caratteri e la inizializza con dati letti da tastiera.
Mostra codiceL’allocazione dinamica di un record avviene analogamente attraverso l’uso dell’operatore new
Indicato con R
un tipo record e con r un puntatore ad R
, si ha:
R* r = new R;
Dichiarazione di un tipo (record) Punto, allocazione dinamica di una variabile di tipo Punto e sua inizializzazione.
Mostra codiceOutput ottenuto nel caso della Definizione 1
Mostra codiceOutput ottenuto nel caso della Definizione 2
Mostra codicevoid Inizializza_Persona(Persona & P) {
cout << "\n inserire Nome e Cognome: ";
cin.getline(P.Nome, dim-1);
cout << "\n inserire l'eta': "; cin >> P.eta;
}
void Inizializza_Persona(Persona & P) {
char Buffer[dim];
cout << "\n inserire Nome e Cognome: ";
cin.getline(Buffer, dim-1);
P.Nome=new char [strlen(Buffer)+1];
strcpy(P.Nome,Buffer);
cout << "\n inserire l'eta': "; cin >> P.eta;
}
Allocazione dinamica di una variabile di tipo puntatore ed inizializzazione dell’area allocata
Mostra codiceint** A= new int*[n];
for (int i=0; i<n; i++)
A[i]= new int[m];
for (int i=0; i<n; i++)
//
dealloca gli n vettori che sono le righe della matrice
delete [] A[i];
delete [] A;
// dealloca il vettore di puntatori alle righe
Tipici errori quando si usa l’allocazione dinamica sono:
1. Strutture e typedef. Record in C/C++: Concetti Base
4. Puntatori a tipi di dato strutturati. Allocazione Dinamica
5. Puntatori: aspetti avanzati
7. Asserzioni
8. Gestione delle eccezioni. Concetti base
9. Programmazione modulare: concetti base
10. Programmazione Modulare: Meccanismi e Strumenti a supporto in C/C++
12. Esercitazione: Strutture Dati Pila e Coda
13. Esercitazione. Strutture Dati: Lista Concatenata
14. Meccanismi di Incapsulamento in C++ Namespaces
15. Programmazione orientata agli oggetti. Introduzione
C. Savy: Da C++ ad UML, McGraw-Hill, Cap. 8, par. 8.3.1, 8.3.5, 8.4
Da Fondamenti di Informatica II, Parte II, Capitolo VII, §6.1, §6.2