Condividi tramite


Puntatori const e volatile

Le parole chiave const e volatile modificano la modalità di trattamento dei puntatori. La parola chiave specifica che il puntatore non può essere modificato dopo l'inizializzazione. Il const puntatore è protetto dalla modifica successivamente.

La volatile parola chiave specifica che il valore associato al nome che segue può essere modificato da azioni diverse da quelle nell'applicazione utente. Pertanto, la volatile parola chiave è utile per dichiarare oggetti in memoria condivisa a cui è possibile accedere da più processi o aree dati globali usate per la comunicazione con routine del servizio interrupt.

Quando un nome viene dichiarato come volatile, il compilatore ricarica il valore dalla memoria ogni volta che si accede al programma. In questo modo vengono ridotte notevolmente le ottimizzazioni possibili. Tuttavia, quando lo stato di un oggetto può cambiare in modo imprevisto, questo è l'unico modo per garantire prestazioni del programma prevedibili.

Per dichiarare l'oggetto a cui punta il puntatore come const o volatile, utilizzare una dichiarazione del formato:

const char *cpch;
volatile char *vpch;

Per dichiarare il valore del puntatore, ovvero l'indirizzo effettivo archiviato nel puntatore, come const o volatile, usare una dichiarazione del formato:

char * const pchc;
char * volatile pchv;

Il linguaggio C++ impedisce le assegnazioni che consentono la modifica di un oggetto o di un puntatore dichiarato come const. Tali assegnazioni rimuoverebbero le informazioni utilizzate per dichiarare l'oggetto o il puntatore, violando pertanto lo scopo della dichiarazione originale. Si considerino le dichiarazioni seguenti:

const char cch = 'A';
char ch = 'B';

Date le dichiarazioni precedenti di due oggetti (cch, di tipo const char e ch, di tipo char), le dichiarazioni/inizializzazioni seguenti sono valide:

const char *pch1 = &cch;
const char *const pch4 = &cch;
const char *pch5 = &ch;
char *pch6 = &ch;
char *const pch7 = &ch;
const char *const pch8 = &ch;

La dichiarazione e le inizializzazioni seguenti non sono corrette.

char *pch2 = &cch;   // Error
char *const pch3 = &cch;   // Error

La dichiarazione di pch2 definisce un puntatore tramite cui un oggetto costante potrebbe essere modificato e pertanto non è consentita. La dichiarazione di pch3 specifica che il puntatore è costante, non l'oggetto. La dichiarazione non è consentita per lo stesso motivo per cui la pch2 dichiarazione non è consentita.

Le otto assegnazioni seguenti mostrano l'assegnazione mediante il puntatore e la modifica del relativo valore per le dichiarazioni precedenti. Si supponga per il momento che l'inizializzazione sia corretta per pch1 tramite pch8.

*pch1 = 'A';  // Error: object declared const
pch1 = &ch;   // OK: pointer not declared const
*pch2 = 'A';  // OK: normal pointer
pch2 = &ch;   // OK: normal pointer
*pch3 = 'A';  // OK: object not declared const
pch3 = &ch;   // Error: pointer declared const
*pch4 = 'A';  // Error: object declared const
pch4 = &ch;   // Error: pointer declared const

I puntatori dichiarati come volatile, o come combinazione di const e volatile, rispettano le stesse regole.

I puntatori agli const oggetti vengono spesso usati nelle dichiarazioni di funzione come indicato di seguito:

errno_t strcpy_s( char *strDestination, size_t numberOfElements, const char *strSource );

L'istruzione precedente dichiara una funzione, strcpy_s, dove due dei tre argomenti sono di tipo puntatore a char. Poiché gli argomenti vengono passati per riferimento e non per valore, la funzione sarà libera di modificare e strDestinationstrSource se strSource non fosse dichiarata come const. La dichiarazione di strSource come const assicura il chiamante che strSource non può essere modificato dalla funzione chiamata.

Nota

Poiché esiste una conversione standard da typename a consttypename**, è possibile passare un argomento di tipo char * a strcpy_s. Tuttavia, il contrario non è vero; non esiste alcuna conversione implicita per rimuovere l'attributo const da un oggetto o da un puntatore.

Un const puntatore di un determinato tipo può essere assegnato a un puntatore dello stesso tipo. Tuttavia, un puntatore che non const può essere assegnato a un const puntatore. Nel codice seguente vengono mostrate le assegnazioni corrette e quelle non corrette:

// const_pointer.cpp
int *const cpObject = 0;
int *pObject;

int main() {
pObject = cpObject;
cpObject = pObject;   // C3892
}

Nell'esempio seguente viene illustrato come dichiarare un oggetto come const se si dispone di un puntatore a un puntatore a un oggetto.

// const_pointer2.cpp
struct X {
   X(int i) : m_i(i) { }
   int m_i;
};

int main() {
   // correct
   const X cx(10);
   const X * pcx = &cx;
   const X ** ppcx = &pcx;

   // also correct
   X const cx2(20);
   X const * pcx2 = &cx2;
   X const ** ppcx2 = &pcx2;
}

Vedi anche

Puntatorinon elaborati