Domanda

$ 5.2.11/7 - [NOTA: a seconda del tipo di oggetto, un'operazione di scrittura tramite puntatore, lValue o puntatore al membro dei dati risultante da un const_cast che getta via un cost -qualificatore68) Maggio produrre comportamenti indefiniti (7.1.5.1). ] "

Le parole di questa sezione (C ++ 03) sono sorprendenti per me. Ciò che è sorprendente sono due cose.

a) In primo luogo, l'uso di "May". Perché è 'May'? Altri posti nello standard sono molto definitivi sul comportamento indefinito

b) Perché è il lancio della costiness di un oggetto originariamente const non immediatamente "comportamento indefinito". Perché è necessaria una scrittura per essere attivata UB?

È stato utile?

Soluzione

a) In primo luogo, l'uso di "May". Perché è 'May'? Altri posti nello standard sono molto definitivi sul comportamento indefinito

Non guardare troppo profondamente nell'uso della parola Maggio qui. Il punto è che la costosa costine in questo caso provoca comportamenti indefiniti.

Lo standard C ++ usa "può" o "potrebbe" spesso, come in:

1.3.12: comportamento indefinito Maggio Ci si aspetta anche quando questo standard internazionale omette la descrizione di qualsiasi definizione esplicita di comportamento.

Enfasi la mia. Fondamentalmente, lo standard usa la parola "può" come in "è consentito".

b) Perché è il lancio della costiness di un oggetto originariamente const non immediatamente "comportamento indefinito". Perché è necessaria una scrittura per essere attivata UB?

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

Altri suggerimenti

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

L'idea è che i dati fondamentalmente const potrebbero essere caricati in una parte di memoria di sola lettura e scrivere a ciò non funzionerà. Tuttavia, è garantito che funzioni correttamente se l'oggetto in questione è fondamentalmente mutabile.

Ex:

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 fornito è:

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 è specificamente consentito.

Per la tua prima domanda, se qualcosa Maggio Produrre comportamenti indefiniti, quindi non lo rende meno indefinito.

Per la seconda parte, immagino che sia per motivi di interoperabilità. Ad esempio, C non (o no, prima di C99) ha a const Parola chiave, quindi se si desidera passare un oggetto const a una funzione C, la costine dovrebbe essere gettata via. Quindi lo standard C ++ specifica che ciò è consentito fintanto che non vengono eseguite le scritture. Se la funzione C è di sola lettura, la costine può essere gettata in sicurezza.

Anche in C ++, anche in modo incoerente o incompleta è abbastanza comune. Quindi occasionalmente ci imbattiamo in situazioni in cui dobbiamo eliminare la costiera per passare un oggetto const a una funzione che non modifica la sua argomentazione, ma lo prende in non controstrino.

Credo che sia perché a const L'oggetto può essere memorizzato nella memoria di sola lettura. Pertanto, scriverne può avere molti effetti: crash del programma, errore di segmentazione o nessun effetto.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top