Zusammenfassungen

Universitätsnotizen im Markdown-Format aus Obsidian.

Gestione della memoria

download MD herunterladen

Puntatori

Le variabili puntatore contengono indirizzi di memoria di altre variabili. Mentre le variabili normali contengono un valore diretto (Riferimento Diretto), i puntatori contengono l'indirizzo di una variabile che ha uno specifico valore (Riferimento Indiretto) .

Dichiarazione: Si usa il simbolo * tra il tipo e il nome.

  • int *ptr; (Puntatore a un intero).
  • Attenzione: in dichiarazioni multiple l'asterisco va ripetuto: int *ptr1, *ptr2;.

Operatori Fondamentali:

  1. Indirizzo (&): Restituisce l'indirizzo di memoria della variabile.
    • Es. ptr = &x; (Assegna a ptr l'indirizzo di x).
  2. *Dereferenziazione (``):** Restituisce il valore dell'oggetto puntato (accede al contenuto all'indirizzo).
    • Es. cout << *ptr; (Stampa il valore della variabile puntata da ptr).
    • Nota: * e & sono operatori inversi: *&y == y.

Puntatori Nulli: Possono essere inizializzati a 0, NULL o nullptr (C++11). Dereferenziare un puntatore nullo causa un errore di Segmentation Fault (crash del programma). Puntatori Pendenti (Dangling Pointers): Un puntatore che punta a un'area di memoria non più valida (es. una variabile locale uscita dallo scope). Dereferenziarlo causa comportamento indefinito.

Puntatori e Costanti (const)

Il qualificatore const modifica il comportamento del puntatore:

  1. Puntatore a Costante: Il valore puntato non può cambiare, ma il puntatore può cambiare indirizzo.

    • const int *ptr = &x;
    • *ptr = 5; -> ERRORE
    • ptr = &y; -> OK.
  2. Puntatore Costante: L'indirizzo contenuto nel puntatore non può cambiare, ma il valore puntato sì. Deve essere inizializzato subito.

    • int * const ptr = &x;
    • ptr = &y; -> ERRORE
    • *ptr = 5; -> OK.
  3. Puntatore Costante a Costante: Né l'indirizzo né il valore possono cambiare.

    • const int * const ptr = &x;.

      Riferimenti (References)

      Un riferimento è un alias (un altro nome) per una variabile esistente.

    • Sintassi: int &ref = x;.
    • Qualsiasi operazione su ref ha effetto su x.

Regole e Differenze con i Puntatori:

  • Deve essere inizializzato alla dichiarazione.
  • Non può essere NULL.
  • Non può essere cambiato per riferirsi a un'altra variabile dopo l'inizializzazione (non si può "reseatare").

    Aritmetica dei Puntatori

    Operazioni valide sui puntatori (utili soprattutto con gli array):

    1. Incremento/Decremento (++, --): Sposta il puntatore alla locazione di memoria successiva/precedente in base alla dimensione del tipo di dato.
      • Es. Se int occupa 4 byte e ptr è 3000, ptr++ diventa 3004.
    2. Somma/Sottrazione Intero (+, -): Sposta il puntatore di N posizioni.
    3. Differenza tra Puntatori: Restituisce il numero di elementi tra due indirizzi.
    4. Relazione Array-Puntatori: Il nome di un array è un puntatore costante al primo elemento. V[i] è equivalente a *(V + i).

      Memoria Dinamica (Heap)

      La memoria allocata staticamente (es. int A[10]) è decisa a tempo di compilazione. Per decidere la quantità di memoria a tempo di esecuzione, si usa lo Heap (Free Store).

      Operatore new

      Alloca memoria nello Heap e restituisce un puntatore.

  • Variabile singola: int *p = new int(5); (alloca e inizializza a 5).
  • Array dinamico: int *arr = new int[dimensione];.

    Operatore delete

    Dealloca la memoria per evitare Memory Leaks (perdita di memoria).

  • Variabile singola: delete p;.
  • Array dinamico: delete[] arr; (fondamentale le parentesi quadre!).

Errori Comuni:

  1. Memory Leak: Dimenticare delete (la memoria rimane occupata fino al termine del programma).
  2. Double Free: Applicare delete due volte sullo stesso puntatore.
  3. Accesso dopo Delete: Usare un puntatore dopo aver liberato la memoria (il puntatore è dangling).

    Matrici Dinamiche

    Si realizzano come array di puntatori (puntatore a puntatore).

  4. Allocazione array di puntatori (righe): int **M = new int*[righe];
  5. Allocazione di ogni riga: M[i] = new int[colonne]; .
  6. Deallocazione inversa: prima le righe (delete[] M[i]), poi l'array di puntatori (delete[] M) .