2011-12-20 18 views
8

Estoy seguro de que el siguiente código no debería compilarse. ¡Pero, en g ++, compila! Véalo compilar en http://codepad.org/MR7Dsvlz.¿Es un molde de (puntero a const) a (puntero a no const) inválido C++?

El código:

#include <iostream> 

using namespace std; 

int main() { 
    int x = 32 ; 
    // note: if x is, instead, a const int, the code still compiles, 
    // but the output is "32". 

    const int * ptr1 = & x ; 

    *((int *)ptr1) = 64 ; // questionable cast 
    cout << x ;   // result: "64" 
} 

Es g ++ un error de compilación de este?

+0

Si desea descartar constness (y está seguro de que está permitido) la forma idiomática de C++ para hacerlo es con 'const_cast (ptr1)' - aunque el molde de C también funcionará, como acaba de ver . –

+1

Esto útil para leer: http://stackoverflow.com/questions/357600/is-const-cast-safe – Pubby

Respuesta

9

No. Según §5.4.4 de la norma C++, los moldes que se pueden realizar por un elenco de estilo C son:

— a const_cast (5.2.11), 
— a static_cast (5.2.9), 
— a static_cast followed by a const_cast, 
— a reinterpret_cast (5.2.10), or 
— a reinterpret_cast followed by a const_cast 

Esto es ampliamente conocido como "arrojando const -ness" , y el compilador no cumpliría esa parte del estándar si no compilara ese código.

Como señala ildjarn, la modificación de un objeto const mediante la eliminación const ness es un comportamiento indefinido. Este programa no muestra un comportamiento indefinido porque, aunque es un objeto señalado por el puntero a const, el objeto en sí no es const (gracias R.Martinho y eharvest por corregir mi mala lectura).

+0

"No." - Entonces, g ++ debería haber compilado el código? "el compilador no cumpliría con esa parte del estándar si no compilara ese código". - Entonces g ++ cumple con esa parte del estándar? –

+0

@noshenim su pregunta fue "¿Es g ++ por error al compilar esto?" a lo que respondí "No". Entonces g ++ debe, y lo hace, compilar el código, y se ajusta a esa parte del estándar. –

+3

Noshenim, usted hizo preguntas contradictorias. Cualquier respuesta * sí * a su pregunta del título fue una * respuesta * a la pregunta del cuerpo. Tenga más cuidado la próxima vez. –

3

No. g ++ no tiene ningún error al compilar el código. el elenco que has hecho es válido.

(int *)ptr1 es un elenco de c. el equivalente en C++ es const_cast<int*>(ptr1). el segundo estilo es más claro de leer.

pero, la necesidad de hacer este molde (para modificar una variable const) muestra un problema en el diseño.

1

La línea *((int *)ptr1) = 64 es equivalente a *(const_cast<int*>(ptr1)) = 64 La const_cast es la primera conversión que se realiza cuando utiliza la notación de conversión.

Cuestiones relacionadas