Pregunta

$ 5.2.11/7 - [Nota: Dependiendo del tipo de objeto, una operación de escritura a través del puntero, LValue o puntero al miembro de datos resultante de un const_cast que arroja un constalificador constante68) mayo producir comportamiento indefinido (7.1.5.1).

Las palabras de esta sección (C ++ 03) son sorprendentes para mí. Lo que es sorprendente son dos cosas.

a) En primer lugar, el uso de 'May'. ¿Por qué es 'May'? Otros lugares en el estándar son muy definitivos sobre el comportamiento indefinido

b) ¿Por qué es que el lanzamiento de la Conoceria de un objeto de constante no es "comportamiento indefinido" de inmediato? ¿Por qué se requiere una escritura para que se active UB?

¿Fue útil?

Solución

a) En primer lugar, el uso de 'May'. ¿Por qué es 'May'? Otros lugares en el estándar son muy definitivos sobre el comportamiento indefinido

No mires demasiado profundamente en el uso de la palabra mayo aquí. El punto es que expulsar la Conoceria en este caso causa un comportamiento indefinido.

El estándar C ++ usa "puede" o "podría" a menudo, como en:

1.3.12: Comportamiento indefinido mayo También se espera cuando este estándar internacional omita la descripción de cualquier definición explícita de comportamiento.

Énfasis mío. Básicamente, el estándar usa la palabra "puede" como en "se le permite".

b) ¿Por qué es que el lanzamiento de la Conoceria de un objeto de constante no es "comportamiento indefinido" de inmediato? ¿Por qué se requiere una escritura para que se active UB?

Una escritura desencadena UB porque es posible que los objetos constante se puedan almacenar en la memoria de solo lectura en ciertas plataformas.

Otros consejos

Tengo entendido que solo será UB si el objeto en cuestión es fundamentalmente un objeto const en lugar de un puntero constante o referencia a un objeto que originalmente no era const.

La idea es que los datos que son fundamentalmente const se pueden cargar en una porción de memoria de solo lectura, y escribir a eso simplemente no va a funcionar. Sin embargo, está garantizado que funcione correctamente si el objeto en cuestión es fundamentalmente mutable.

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.

Para un comentario a continuación, porque el código se ve terrible en los comentarios:

En §7.1. 5.1/4 del estándar, el ejemplo dado es:

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

Entonces esto está específicamente permitido.

Para tu primera pregunta, si algo mayo Producir un comportamiento indefinido, entonces eso no lo hace menos indefinido.

Para la segunda parte, me imagino que es por razones de interoperabilidad. Por ejemplo, C no (o no, antes de C99) tiene un const Palabra clave, por lo que si desea pasar un objeto const a una función C, la Constura tendría que ser expulsada. Entonces, el estándar C ++ especifica que esto está permitido siempre que no se realicen escrituras. Si la función C es de solo lectura, la Conste se puede eliminar de manera segura.

Incluso en C ++, la corrección constante o incompleta de constante también es bastante común. Por lo tanto, ocasionalmente nos encontramos con situaciones en las que tenemos que expulsar la constante para pasar un objeto const a una función que no modifica su argumento, pero lo toma por no const.

Creo que eso es porque un const El objeto se puede almacenar en memoria de solo lectura. Por lo tanto, escribirle puede tener muchos efectos diferentes: bloqueo del programa, falla de segmentación o ningún efecto.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top