2011-10-27 11 views
38

Cosa significa const nel qualificatore di "livello superiore" in C++?Quali sono i qualificatori const di livello superiore?

E quali sono gli altri livelli?

Ad esempio:

int const *i; 
int *const i; 
int const *const i; 
+3

esempi, per favore? – bmargulies

+0

Non so cosa intendi con esempi, ma ho aggiunto alcuni qualificatori di const con cui ho familiarità. – user103214

+3

Vedere anche [Qual è la definizione di 'cv-qualificatori di primo livello 'nello standard C++ 11?] (Http://stackoverflow.com/q/24676824/1708801) –

risposta

49

Un qualificatore const livello superiore colpisce l'oggetto stesso. Altri sono solo pertinenti con puntatori e riferimenti. Non creano l'oggetto const e impediscono solo la modifica tramite un percorso utilizzando il puntatore o il riferimento . Quindi:

Questo non è un const di livello superiore e nessuno degli oggetti è immutabile. L'espressione *p non può essere utilizzata per modificare , ma altre espressioni possono essere; x non è const. Per quello che riguarda

*const_cast<char*>(p) = 't' 

è legale e ben definito.

Ma

char const x = 't'; 
char const* p = &x; 

Questa volta, c'è un const di alto livello sulla x, quindi x è immutabile. Nessuna espressione è consentita per modificarlo (anche se si utilizza const_cast). Il compilatore può inserire x nella memoria di sola lettura e può assumere che il valore di x non cambi mai, indipendentemente da ciò che altro codice può fare.

Per dare il puntatore di livello superiore const, devi scrivere:

char x = 't'; 
char *const p = &x; 

In questo caso, p punterà x per sempre; qualsiasi tentativo di modificare questo è un comportamento non definito (e il compilatore può inserire p nella memoria di sola lettura, o assumere che *p si riferisce a x, indipendentemente da qualsiasi altro codice).

+3

Molto chiaro, grazie :) – Seb

+6

Un altro punto: quando si scrivono le funzioni i qualificatori di livello superiore degli argomenti vengono scartati. Ciò significa che 'void foo (char const)' e 'void foo (char)' sono la stessa funzione (e infatti possono essere scambiati). Il ragionamento è che poiché l'argomento è preso dalla copia, al chiamante non importa se la copia può essere modificata o meno, quindi è trasparente per lei. –

+7

@MatthieuM. Buon punto, anche se non esattamente vero come affermato. I qualificatori di primo livello vengono ignorati in una dichiarazione e nel tipo di funzione. Nella definizione, tuttavia, si comportano ancora come al solito all'interno della funzione. (I qualificatori di primo livello vengono ignorati anche dai parametri 'typeid' e template, quando si combinano le eccezioni da catturare e probabilmente in altri casi che ho dimenticato.In pratica, non hanno alcun effetto sui valori di ritorno del tipo non di classe.) –

10

int *const i mette const al livello superiore, mentre int const *i no.

Il primo indica che il puntatore i non è immutabile, mentre il secondo indica che la memoria a cui punta il puntatore è immutabile.

Ogni volta che const appare immediatamente prima o dopo il tipo dell'identificatore, viene considerato un qualificatore di primo livello.

+0

Risposta eccellente e chiara. Post scriptum 'int const * i' è uguale a' const int * i' (tutti sono const di basso livello). Io uso 'const int * i' (low-level) per distinguere il suo livello const più spesso da' int * const i' (top-level). – dotslash

5

Il modo in cui è stato spiegato a me, data:

[const] TYPE * [const] VARIABLE 

VARIABILE è usato per puntare a dati di tipo TIPO attraverso *VARIABLE

Tracciare una linea attraverso il * o multiple * s

  1. Se c'è una const al sinistra del * si applica ai dati ei dati non possono essere modificati: *VARIABLE non può essere assegnato, tranne all'inizializzazione
  2. Se c'è una const al destra del * si applica al VARIABILE e quali sono le VARIABILI punti non possono essere modificati: VARIABLE non può essere assegnato, se non a initiali zazione

Quindi:

  |    left right 
int  *  i1; 
      |    no no  can change *i1 and i1 

int const *  i2;  
      |    yes no  cannot change *i2 but can change i2 

int  * const i3; 
      |    no yes can change *i3 but i3 cannot be changed 

int const * const i4; 
      |    yes yes cannot change *i4 or i4 
+0

'const' si lega a sinistra. a meno che non ci sia nulla a sinistra, poi si lega a destra – sp2danny

Problemi correlati