2010-10-28 10 views
5

$ 5.2.11/7 - "[Nota: A seconda del tipo di oggetto, un'operazione di scrittura attraverso il puntatore, lvalue o il puntatore al membro di dati risultante da un const_cast che getta via un const-qualifier68) può produrre comportamento non definito (7.1.5.1).]"const_cast e UB

la formulazione di questo paragrafo (C++ 03) sono sorprendente per me. Ciò che è sorprendente sono due cose.

a) In primo luogo, l'uso di "può". Perché è "possibile"? Altri posti nello standard sono molto definitivi sul comportamento non definito

b) Perché è il castare la costanza di un oggetto const originale non immediatamente 'comportamento indefinito'. Perché è necessaria una scrittura per l'attivazione di UB?

+0

Mi riferisco ai lettori della risposta di Kaz Dragon - '7.1.5.1/4' - che penso chiarisca che questo non è UB se l'oggetto originale non è stato dichiarato' const'. La formulazione dello Standard in questo bit è incredibilmente ambigua. Ma c'è un esempio di codice scritto deliberatamente nello stesso respiro che indica che la scrittura tramite un 'const_cast'ed ref/ptr su un oggetto originariamente non' '' '' '' '' '' '' '' '', come considero più autorevole di un paragrafo con "dipendente" e "può" in esso. ;) –

risposta

4

a) In primo luogo, l'uso di "può". Perché è "può"? Altri luoghi della standard sono molto definitive circa il comportamento non definito

Non guardare troppo in profondità nel uso della parola può qui. Il punto è che la determinazione della costanza in questo caso causa un comportamento indefinito.

serie La C++ utilizza "può" o "potrebbe", spesso, come in:

1.3.12: un comportamento indefinito può anche essere previsto quando questo norma internazionale omette la descrizione di qualsiasi esplicito definizione di comportamento.

Enfasi mia.Fondamentalmente, lo standard usa la parola "può" come in "is allowed to".

b) Perché è che il getto via la costanza di un oggetto originariamente const non subito 'undefined comportamento'. Perché una scrittura è richiesta per l'attivazione di UB?

Una scrittura attiva UB perché è possibile che gli oggetti const possano essere memorizzati nella memoria di sola lettura su determinate piattaforme.

+0

in realtà non risponde alla mia terza domanda .... – Chubsdad

1

Credo che sia perché un oggetto const può essere memorizzato nella memoria di sola lettura. Pertanto, scrivendo su di esso può avere molti effetti diversi: arresto anomalo del programma, errore di segmentazione o nessun effetto.

3

La mia comprensione è che sarà solo UB se l'oggetto in questione è fondamentalmente un oggetto const anziché un puntatore const o un riferimento a un oggetto che non era originariamente const.

L'idea è che i dati che sono fondamentalmente const potrebbero essere caricati in una porzione di memoria di sola lettura, e scrivere su quello non funzionerà. Tuttavia, è garantito che funzioni correttamente se l'oggetto in questione è fondamentalmente mutevole.

Es:

const int x = 4; 
const int *y = x; 

*const_cast<int*>(x) = 3; // UB - the pointed-to object may 
          // be in read-only memory or whatever. 

int  a = 7; 
const int *b = a; 

*const_cast<int*>(b) = 6; // Not UB - the pointed-to object is 
          // fundamentally mutable. 

Per un commento qui sotto, perché il codice sembra terribile nei commenti:.

In §7.1 5,1/4 dello standard, l'esempio è:

int i = 2; 
const int * cip; // pointer to const int 
cip = &i;  // OK: cv-qualified access path to unqualified 
... 
int* ip; 
ip = const_cast <int *>(cip); // cast needed to convert const int* to int* 
*ip = 4;      // defined: *ip points to i, a non-const object 

Quindi questo è espressamente consentito.

+0

Non sono d'accordo. Standard C++. '§ 7.1.1 5.1/4 dice Tranne che qualsiasi membro della classe dichiarato mutabile (7.1.1) può essere modificato, qualsiasi tentativo di modificare un oggetto const durante la sua vita (3.8) comporta un comportamento indefinito ** Qualsiasi tentativo! ** –

+1

@Alexey - Ora guarda l'esempio per §7.1. 5.1/4 esattamente sotto dove hai citato. In particolare consente questo caso. Ho aggiunto il codice alla risposta sopra perché il codice sembrava terribile qui. –

+0

+1 per '7.1.5.1/4'. Credo che il testo citato in questione è scritto male nel migliore dei casi, pericolosamente contraddittorio nel peggiore dei casi. Ma prendo un esempio di codice scritto deliberatamente affermando che questo è ben definito come più autorevole di un paragrafo con "dipendente" e "può" in esso. –

3

Per la prima domanda, se qualcosa di può produrre, un comportamento non definito, quindi non lo rende meno indefinito.

Per la seconda parte, immagino che sia per motivi di interoperabilità. Ad esempio, C non ha (o non ha, prima di C99) una parola chiave const, quindi se si desidera passare un oggetto const a una funzione C, è necessario deviare la costante. Quindi lo standard C++ specifica che questo è permesso purché non vengano eseguite scritture. Se la funzione C è di sola lettura, la costanza può essere castata in modo sicuro.

Anche in C++, la cost-correctness incoerente o incompleta è piuttosto comune. Quindi occasionalmente ci imbattiamo in situazioni in cui dobbiamo gettare via const-ness per passare un oggetto const a una funzione che non modifica il suo argomento, ma la prende per non-const.

+0

Aspetta ... cosa? Sono abbastanza sicuro che C89 ha 'const'. Vedere la sezione 3.5.3 "Tipo di qualificazione" in http://flash-gordon.me.uk/ansi.c.txt –

+0

C89 ha const, ma un sacco di vecchio e/o di-merda-ma-utili C (e anche C++) le API non lo usano comunque. –

+0

Oh, strano. Mi chiedo cosa mi abbia dato l'idea che non sia così. Sono corretto. :) – jalf

Problemi correlati